home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / Think Class Libraries / CommToolbox (modified) / Sources / CTermPane.cp < prev    next >
Encoding:
Text File  |  1994-11-30  |  76.5 KB  |  3,319 lines  |  [TEXT/KAHL]

  1. /* ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  2.  
  3.     CTermPane.c
  4.     
  5.     Commtoolbox terminal emulation class.
  6.     
  7.     SUPERCLASS = CPanorama.
  8.     
  9.     Original copyright © 1992-93 Romain Vignes. All rights reserved.
  10.     Modifications copyright © 1994-95 Ithran Einhorn. All rights reserved.
  11.     
  12. ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ */
  13.  
  14. #include "CTermPaneDef.h"
  15.  
  16. /* Class Variables Initialization */
  17.  
  18. CCluster    *CTermPane::cTermList = NULL;
  19.  
  20. /*
  21.  * cTermIdle
  22.  *
  23.  * Idle time for each terminal object
  24.  *
  25.  *
  26.  */
  27.  
  28.          /* Idle routine for each terminal object */
  29.  
  30.         static void    Term_Idle(CTermPane *theTerm)
  31.         {
  32.             theTerm->DoIdle();
  33.         }
  34.  
  35.  
  36. void CTermPane::cTermIdle(void)
  37. {
  38.     if (cTermList != NULL)        /* List exists ? */
  39.         cTermList->DoForEach((EachFunc) Term_Idle);
  40. }    
  41.  
  42.  
  43. /* ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ */
  44.  
  45. /*
  46.  * cInitManager
  47.  *
  48.  * Terminal Manager Initialization
  49.  *
  50.  */
  51.  
  52. void CTermPane::cInitManager(void)
  53. {
  54.     InitTM();
  55. }    
  56.  
  57.  
  58. /* ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ */
  59.  
  60. /*
  61.  * cGetTMVersion
  62.  *
  63.  * return the version of the Terminal Manager
  64.  *
  65.  */
  66.  
  67. short CTermPane::cGetTMVersion(void)
  68. {
  69.     return TMGetTMVersion();
  70. }    
  71.  
  72.  
  73. /* ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ */
  74.  
  75. /*
  76.  * cCheckToolName
  77.  *
  78.  * Existence tool checking
  79.  *
  80.  * toolName:    name of the tool
  81.  *
  82.  * Return tmGenericError if the tool is not found
  83.  *
  84.  */
  85.  
  86. OSErr CTermPane::cCheckToolName(Str63 toolName)
  87. {
  88.     return(TMGetProcID(toolName));
  89. }    
  90.  
  91.  
  92. /* ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ */
  93.  
  94. /*
  95.  * cTestToolMenu
  96.  *
  97.  * Test if the selected menu belongs to a terminal tool
  98.  *
  99.  * theMenu:    selected menu ID
  100.  * theItem:    selected item ID
  101.  *
  102.  * Return TRUE if the menu is a terminal tool menu
  103.  */
  104.  
  105.  
  106.          /* Test routine */
  107.  
  108.         static Boolean TermMenuTest(CTermPane *theTerm)
  109.         {
  110.             return theTerm->active;
  111.         }
  112.  
  113.  
  114. Boolean CTermPane::cTestToolMenu(short theMenu, short theItem)
  115. {
  116.     CTermPane    *current;
  117.     
  118.     if (cTermList == NULL)
  119.         return FALSE;
  120.     else    {
  121.         current = (CTermPane *) cTermList->FindItem((TestFunc) TermMenuTest);
  122.         
  123.         if (current == NULL)
  124.             return FALSE;
  125.         else
  126.             return current->DoMenu(theMenu,theItem);
  127.     }
  128. }    
  129.  
  130.  
  131. /* ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ */
  132.  
  133. /*
  134.  * cTestToolEvent
  135.  *
  136.  * Test if the event is related to a terminal tool
  137.  *
  138.  * macEvent:    pointer on the event record
  139.  * theWindow:    pointer on the window record
  140.  *
  141.  * Return TRUE if the event is a terminal event
  142.  */
  143.  
  144. typedef struct    {
  145.     EventRecord    *theEvent;
  146.     WindowPtr    theWindow;
  147.     Boolean        isToolEvent;
  148. } TestParamRec;
  149.  
  150.  
  151.          /* Test routine */
  152.  
  153.         static void TermEvtTest(CTermPane *theTerm,TestParamRec *params)
  154.         {
  155.             if (params->isToolEvent == FALSE)
  156.                 params->isToolEvent = theTerm->DoEvent(params->theEvent,
  157.                     params->theWindow);
  158.         }
  159.  
  160.  
  161. Boolean CTermPane::cTestToolEvent(EventRecord *macEvent,WindowPtr theWindow)
  162. {
  163.     TestParamRec params;
  164.     
  165.     params.theEvent = macEvent;
  166.     params.theWindow = theWindow;
  167.     params.isToolEvent = FALSE;
  168.     
  169.     if (cTermList == NULL)
  170.         return FALSE;
  171.     else    {
  172.         cTermList->DoForEach1((EachFunc1) TermEvtTest,(long) ¶ms);
  173.         
  174.         return params.isToolEvent;
  175.     }
  176. }    
  177.  
  178.  
  179. /* ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ */
  180.  
  181. /*
  182.  * ITermPane
  183.  * 
  184.  * Terminal pane object Initialization
  185.  *
  186.  * anEnclosure:        its enclosure view
  187.  * aSupervisor:        its supervisor in the chain of command
  188.  * toolName:        Terminal tool name ("" -> default tool)
  189.  * flags(TM):        How to use the tool
  190.  * sendProc(TM):    Pointer on the chars sending procedure
  191.  * cacheProc(TM):    Pointer on the cach managing procedure
  192.  * breakProc(TM):    Pointer on the BREAK signal sending procedure
  193.  * clickLoop(TM):    Pointer on the clics handling sending procedure
  194.  * environsProc(TM):Pointer on the environnement description procedure
  195.  * refCon(TM):        undefined (application can use it)
  196.  * userData(TM):    undefined (application can use it)
  197.  *
  198.  * Parameters followed by TM are exactly matching the ones used for the 
  199.  * terminal record creation.
  200.  *
  201.  */
  202.  
  203. void CTermPane::ITermPane(CView *anEnclosure, CBureaucrat *aSupervisor,
  204.                             Str63 toolName,Str63 commName,Str63 xferName,TMFlags flags,TMSendProcPtr sendProc,
  205.                             TMCacheProcPtr cacheProc,TMBreakProcPtr breakProc,TMClickProcPtr clickLoop,
  206.                             TMEnvProcPtr environsProc,long refCon,long userData,Boolean isAsync,long TimeOut)
  207.  
  208. {
  209.     LongRect        lRect,newBounds;
  210.     Rect            termRect,viewRect;
  211.     LongRect        paneRect;
  212.     OSErr            theErr;
  213.     short            toolProcID;
  214.     WindowPtr        owner;
  215.     Boolean            savedAlloc;
  216.     TermHandle        hTerm;
  217.     Str63            tName;
  218.     TermEnvironRec    theEnvirons;
  219.     ConnHandle        theConn;
  220.     CMBufferSizes    bufSizes;
  221.     
  222.     static unsigned char *szToolName = (unsigned char *)"";    // default tool name.
  223.     
  224.     inherited::IAbstractText(anEnclosure, aSupervisor,0,0,0,0,
  225.                                 sizELASTIC, sizELASTIC,-1);        /* Initialize 
  226.                                                                 its superclass */                        
  227.     asyncRead = isAsync;
  228.     TimeOutLen = TimeOut;
  229.     itsSelStart = itsSelEnd = itsSelAnchor = 0;
  230.     reallyActive = FALSE;
  231.     topMargin = 0;
  232.     
  233.     owner = (WindowPtr) this->GetMacPort();        /* Window port */
  234.     
  235.     memset(bufSizes,0,sizeof(bufSizes));
  236.     
  237.     bufSizes[cmDataIn] = IOBUFSIZE;
  238.     bufSizes[cmDataOut] = IOBUFSIZE;
  239.     readAmount = 0L;
  240.     numCachedLines = 0L;
  241.     
  242.     itsConnection = new(CConnection);
  243.     itsConnection->IConnection(this,commName,0,bufSizes,0L,0L);
  244.     
  245.     itsFileTransfer = new(CFileTransfer);
  246.     itsFileTransfer->IFileTransfer(this,xferName,0,nil,nil,nil,nil,nil,owner,0L,0L);
  247.     
  248.     theConn = itsConnection->GetConnHandle();
  249.     ReadBuffer = NewPtr((*theConn)->bufSizes[cmDataIn]);
  250.     FailMemError ();
  251.     
  252.     SetRect(&termRect,0,0,0,0);                    /* visible terminal rect */
  253.     SetRect(&viewRect,0,0,0,0);
  254.     
  255.     if (toolName[0] == 0)        /* Default tool ? */
  256.     {
  257.         theErr = CRMGetIndToolName(classTM,1,tName);
  258.         
  259.         if ((theErr != noErr) || (tName[0] == 0))         /* No tool */
  260.             Failure(tmNoTools,SpecifyMsg(TERM_STR_RES_ID,NO_TOOL_STR_INDEX));
  261.  
  262.         toolProcID = cCheckToolName(tName);            /* Default tool ID */
  263.     }
  264.     else
  265.         toolProcID = cCheckToolName(toolName);            /* Chosen tool ID */
  266.     
  267.     if (toolProcID == tmGenericError)            /* Bad tool */
  268.             Failure(tmNoTools,SpecifyMsg(TERM_STR_RES_ID,BAD_TOOL_STR_INDEX));
  269.         
  270.     savedAlloc = SetAllocation(kAllocCanFail);
  271.     
  272.     if (sendProc == nil)
  273.         sendProc = DefSendProc;
  274.         
  275.     if (breakProc == nil)
  276.         breakProc = DefBreakProc;
  277.         
  278.     if (environsProc == nil)
  279.         environsProc = (TMEnvProcPtr)DefEnvironsProc;
  280.         
  281.     if (cacheProc == nil)
  282.         cacheProc = DefCacheProc;
  283.         
  284.     if (clickLoop == nil)
  285.         clickLoop = DefClikLoop;
  286.         
  287.     hTerm = TMNew(&termRect,&viewRect,flags,toolProcID,owner,
  288.                     sendProc,(TerminalCacheProcPtr)cacheProc,breakProc,clickLoop,environsProc,
  289.                     (long)this,userData);
  290.                     
  291.     SetAllocation(savedAlloc);
  292.     
  293.     FailNIL(hTerm);                /* Terminal record created ? */
  294.  
  295.     MoveHHi((Handle)hTerm);        /* Heap fragmentation… */
  296.     
  297.     this->itsTerm = hTerm;
  298.             
  299.     this->SetWantsClicks(TRUE);        
  300.     
  301.     this->SetCanBeGopher(TRUE);        
  302.     this->SetWholeLines(TRUE);        
  303.     
  304.     // create the scroll-back buffer
  305.     itsScrollBuffer = new(CScrollBuffer);
  306.     itsScrollBuffer->IScrollBuffer(kNumCachedLines);
  307.     
  308.     if (cTermList == NULL)    {        /* First Terminal Object ? */
  309.         cTermList = new(CCluster);
  310.         cTermList->ICluster();
  311.     }
  312.     
  313.     cTermList->Add(this);            /* Terminal addition */
  314.     
  315.     this->changedConfig(false);        /* Configuration update */
  316.     
  317.     #ifdef __USETHREADS__
  318.     if (CThread::cIsPresent())
  319.     {
  320.         itsIdleThread = new(CThread);
  321.         itsIdleThread->IThread(kCooperativeThread, (ThreadEntryProcPtr)cOneTermIdle, this);
  322.     }
  323.     #endif
  324. }
  325.  
  326. /* ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ */
  327.  
  328. /*
  329.  * Dispose
  330.  *
  331.  * Terminal pane object disposal
  332.  *
  333.  */
  334.  
  335. void CTermPane::Dispose(void)
  336. {
  337.     ASSERT(cTermList != NULL);
  338.     
  339.     #ifdef __USETHREADS__
  340.     if (CThread::cIsPresent())
  341.     {
  342.         itsIdleThread->Dispose();
  343.     }
  344.     #endif
  345.     
  346.     cTermList->Remove(this);        /* Dispose of the terminal */
  347.     
  348.     if (cTermList->IsEmpty())
  349.         ForgetObject(cTermList);    /* Dispose of the cluster */
  350.  
  351.     TMDispose(itsTerm);                /* Terminal record removal */
  352.     itsTerm = NULL;
  353.     
  354.     ForgetObject(itsFileTransfer);    /* Dispose the file transfer mechanism. */
  355.     ForgetObject(itsConnection);    /* Dispose the connection. */
  356.     ForgetObject(itsScrollBuffer);    /* Dispose scrollback buffer */
  357.     
  358.     ForgetPtr(ReadBuffer);            /* Release read buffer. */
  359.         
  360.     inherited::Dispose();            /* Pass message to its superclass */
  361. }
  362.  
  363.  
  364. /* ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ */
  365.  
  366. /*
  367.  * Draw
  368.  *
  369.  * Terminal pane drawing
  370.  *
  371.  * area:    Pointer on the region to be updated
  372.  *
  373.  */
  374.  
  375. void CTermPane::Draw(Rect *area)
  376. {
  377.     RgnHandle        updateRgn;
  378.     LongRect        longArea;
  379.     long            startLine;
  380.     long            endLine;
  381.     long            numVisible;
  382.     TermEnvironRec    theEnvirons;
  383.         
  384.     Prepare();
  385.             
  386.     updateRgn = NewRgn();
  387.     FailNIL(updateRgn);
  388.     
  389.     RectRgn(updateRgn,area);        /* Transform rect into region */
  390.         
  391.     TMUpdate(itsTerm,updateRgn);
  392.         
  393.     DisposeRgn(updateRgn);
  394.     
  395.     /* Compute and draw the visible cached text lines */
  396.     
  397.     GetEnvirons(&theEnvirons);
  398.     
  399.     if (position.v < numCachedLines)
  400.     {    
  401.         Rect    areaRect;
  402.         short    integralHeight;
  403.     
  404.         QDToFrameR(area, &longArea);
  405.         LongToQDRect(&longArea,&areaRect);
  406.         
  407.         OffsetRect(&areaRect,0,-(theEnvirons.slop.v));
  408.         
  409.         // only draw an integral number of lines
  410.         integralHeight = (RectHeight(&areaRect) / theEnvirons.cellSize.v) * theEnvirons.cellSize.v;
  411.         areaRect.bottom = Min(areaRect.bottom, areaRect.top + integralHeight);
  412.     
  413.         startLine = areaRect.top / theEnvirons.cellSize.v;
  414.         endLine = areaRect.bottom / theEnvirons.cellSize.v;
  415.         
  416.         numVisible = numCachedLines - position.v;
  417.     
  418.         if (startLine < numVisible)
  419.         {    
  420.             endLine = Min(endLine,(numVisible - 1));
  421.             DrawLineRange(startLine, endLine, 0, kDontEraseText);
  422.         }
  423.     }
  424.     
  425.     // draw hilite area.
  426.     if (itsSelStart != itsSelEnd)
  427.         HiliteTextRange(itsSelStart, itsSelEnd);
  428. }
  429.  
  430. /* ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ */
  431.  
  432. /*
  433.  * DrawAllOffscreen
  434.  *
  435.  * Terminal pane drawing
  436.  *
  437.  * area:    Pointer on the region to be updated
  438.  *
  439.  */
  440.  
  441. void CTermPane::DrawAllOffscreen(Rect *area)
  442. {
  443.  LongRect    lsrcRect, ldestRect;
  444.  
  445.  CBitMap *paneBitMap;
  446.  
  447.  Prepare();
  448.  
  449.  GetWindow()->GetAperture(&lsrcRect);
  450.  
  451.  paneBitMap = new(CBitMap);
  452.  paneBitMap->IBitMap(lsrcRect.right - lsrcRect.left, lsrcRect.bottom - lsrcRect.top, TRUE);
  453.  
  454.  paneBitMap->BeginDrawing();
  455.  macPort = paneBitMap->macPort;
  456.  
  457.  DrawAll(area);
  458.  
  459.  macPort = paneBitMap->savePort; 
  460.  paneBitMap->EndDrawing();
  461.  
  462.  QDToLongRect(area, &ldestRect);
  463.  paneBitMap->CopyFrom(&lsrcRect, &lsrcRect, nil);
  464.  paneBitMap->Dispose();
  465. }
  466.  
  467. /* ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ */
  468.  
  469. /*
  470.  * RefreshOffscreen
  471.  *
  472.  * Terminal pane drawing
  473.  *
  474.  *
  475.  */
  476.  
  477. void CTermPane::RefreshOffscreen(void)
  478. {
  479.     LongRect    termAperture;
  480.     Rect        termRect;
  481.     
  482.     GetAperture(&termAperture);
  483.     FrameToQDR(&termAperture,&termRect);
  484.     
  485.     DrawAllOffscreen(&termRect);
  486. }
  487.  
  488. /* ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ */
  489.  
  490. /*
  491.  * DoCommand
  492.  *
  493.  * Terminal pane related commands handling
  494.  *
  495.  * theCommand:    Command to be executed
  496.  *
  497.  */
  498.  
  499. void CTermPane::DoCommand(long theCommand)
  500. {    
  501.     Handle        selectionHdl;
  502.     ResType        selectionType;
  503.     short        scrapLength,i;
  504.     EventRecord    theEvent;
  505.     
  506.     switch (theCommand) {        
  507.     
  508.         case cmdTermChoose:        /* Terminal tool setup */
  509.             this->TermChoose();
  510.             break;
  511.     
  512.         case cmdTermClear:        /* Screen clearing */
  513.             this->TermClear();
  514.             break;
  515.     
  516.         case cmdTermReset:        /* Terminal reset */
  517.             this->Reset();
  518.             break;
  519.     
  520.         case cmdCopy:            /* Copy */
  521.             this->DoCopy();            
  522.             break;
  523.     
  524.         case cmdTabCopy:        /* Table copy */
  525.             this->DoTabCopy();
  526.             break;
  527.             
  528.         case cmdPaste:            /* Paste */
  529.         
  530.             theEvent.what = keyDown;
  531.             
  532.             gClipboard->GetData('TEXT',&selectionHdl);
  533.         
  534.             scrapLength = gClipboard->DataSize('TEXT');
  535.             
  536.             for (i = 0;i < scrapLength;i ++)    {    /* For each char… */
  537.                 theEvent.message = (*selectionHdl)[i];
  538.                 theEvent.modifiers = 0;
  539.                 TMKey(itsTerm,&theEvent);
  540.             }
  541.             DisposHandle(selectionHdl);
  542.             
  543.             break;
  544.             
  545.         case cmdSelectAll:        /* Complete pane selection */
  546.             this->DoSelectAll();
  547.             break;
  548.     
  549.         default:
  550.             inherited::DoCommand(theCommand);
  551.             break;
  552.     }
  553. }
  554.  
  555.  
  556. /* ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ */
  557.  
  558. /*
  559.  * UpdateMenus
  560.  *
  561.  * Terminal tool menus updating
  562.  *
  563.  */
  564.  
  565. void CTermPane::UpdateMenus(void)
  566. {
  567.     Rect        nullRect;
  568.     SignedByte    savedState;
  569.         
  570.     savedState = HGetState((Handle)itsTerm);
  571.     HLock((Handle)itsTerm);
  572.     
  573.     inherited::UpdateMenus();            /* Pass message to its superclass */
  574.     
  575.     //gBartender->EnableCmd( cmdSelectAll);    /* Complete selection */
  576.     
  577.     gBartender->EnableCmd(cmdTermChoose);    /* Terminal tool setup */
  578.     gBartender->EnableCmd(cmdTermClear);    /* Screen clearing */
  579.     gBartender->EnableCmd(cmdTermReset);    /* Terminal reset */
  580.     
  581.     SetRect(&nullRect,0,0,0,0);
  582.     
  583.     if (!EqualRect(&nullRect,&(((*itsTerm)->selection).selRect)))
  584.     {
  585.         gBartender->EnableCmd(cmdCopy);    /* Copier */
  586.         
  587.         if (((*itsTerm)->selType == selTextNormal) ||
  588.             ((*itsTerm)->selType == selTextBoxed))
  589.         {
  590.             gBartender->EnableCmd(cmdTabCopy);    /* Table copy */
  591.         }
  592.     }
  593.         
  594.     if (gClipboard->DataSize('TEXT') > 0)        /* Paste */
  595.         gBartender->EnableCmd(cmdPaste);
  596.         
  597.     HSetState((Handle)itsTerm,savedState);
  598. }
  599.  
  600.  
  601. /* ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ */
  602.  
  603. /*
  604.  * TermChoose
  605.  *
  606.  * Terminal tool setup
  607.  *
  608.  */
  609.  
  610. void CTermPane::TermChoose(void)
  611. {
  612.     short            retCode;
  613.     Point            where;
  614.     TermHandle        hTerm;
  615.     TermRecord        oldRecord;
  616.     TermEnvironRec    theOldEnvirons;
  617.     
  618.     // save the old environment
  619.     GetEnvirons(&theOldEnvirons);
  620.     oldRecord = **itsTerm;
  621.     
  622.     hTerm = this->itsTerm;
  623.     HUnlock((Handle)hTerm);
  624.     
  625.     SetPt(&where,H_CHOOSE_POS,V_CHOOSE_POS);    /* Dialog position */
  626.                                                 
  627.     retCode = TMChoose(&hTerm,where,NULL);
  628.     
  629.     HLock((Handle)hTerm);
  630.     this->itsTerm = hTerm;
  631.  
  632.     switch (retCode)    {        
  633.         case chooseCancel:            /* Canceled setup */
  634.             break;
  635.             
  636.         case chooseOKMajor:            /* Changed tool */
  637.             TermClear();            /* reset scrollback buffer, go on to chooseOKMinor processing */
  638.             
  639.             this->changedConfig();            
  640.             TMActivate(itsTerm,TRUE);            
  641.             itsSupervisor->Notify(NULL);     /* Notify document… */
  642.             
  643.             break;
  644.         
  645.         
  646.         case chooseOKMinor:                    /* Same tool, changed config */
  647.         
  648.             AdjustTermPosition(&oldRecord, &theOldEnvirons);
  649.             
  650.             this->changedConfig();        
  651.             TMActivate(itsTerm,TRUE);            
  652.             itsSupervisor->Notify(NULL);     /* Notify document… */
  653.             
  654.             break;
  655.             
  656.         default:                /* Unknown code (error) */
  657.             FailOSErr(retCode);
  658.             break;    
  659.     }
  660.         
  661. }
  662.  
  663.  
  664. /* ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ */
  665.  
  666. /*
  667.  * DoIdle
  668.  * 
  669.  * Application idle time
  670.  *
  671.  */
  672.  
  673. void CTermPane::DoIdle(void)
  674. {    
  675.     Boolean fXferInProgress = (itsFileTransfer && itsFileTransfer->IsRunningOnSameCircuit ());
  676.     
  677.     Prepare();
  678.     
  679.     TMIdle(itsTerm);
  680.     
  681.     if (itsConnection && itsConnection->IsOpen())
  682.     {
  683.         if (readAmount && readCompleted == true && ! fXferInProgress)
  684.         {
  685.             DoStream(ReadBuffer,readAmount,readFlags);
  686.             readAmount = 0L;
  687.             readCompleted = false;
  688.         }
  689.      
  690.         if (! (itsFileTransfer && itsFileTransfer->NeedsConnection()))
  691.         {
  692.             readAmount = itsConnection->DataAvail();
  693.      
  694.             if (readAmount)
  695.             {
  696.                  Boolean    wasLocked;
  697.  
  698.                  wasLocked = Lock(true);    // we're going to use instance variables in ToolBox routines.
  699.  
  700.                 itsConnection->DataRead(ReadBuffer,&readAmount,
  701.                                         asyncRead,
  702.                                         (CommProcPtr)DefReadCompletedProc,
  703.                                         TimeOutLen,&readFlags);
  704.                 
  705.                 // for synchronous reads, set status to done, else completor routine will.                              
  706.                 if (asyncRead == false)
  707.                     readCompleted = true;
  708.                                                   
  709.                 Lock(wasLocked);
  710.             }
  711.         }
  712.     }
  713.     
  714. }
  715.  
  716. /* ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ */
  717.  
  718. /*
  719.  * cOneTermIdle
  720.  * 
  721.  * terminal idle time
  722.  *
  723.  */
  724.  
  725. pascal void    *CTermPane::cOneTermIdle (void *threadParam)
  726. {
  727.     CTermPane *aTerm = (CTermPane *)threadParam;
  728.     
  729.     #ifdef __USETHREADS__
  730.     for (;;)
  731.     {
  732.         ThreadBeginCritical();
  733.     #endif
  734.  
  735.         aTerm->DoIdle();    
  736.  
  737.     #ifdef __USETHREADS__
  738.         ThreadEndCritical();
  739.         YieldToAnyThread();
  740.     }
  741.     #endif
  742.  
  743.     return nil;
  744. }
  745.     
  746. /* ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ */
  747.  
  748. /*
  749.  * AdjustCursor
  750.  *
  751.  * Cursor shape update
  752.  *
  753.  * where:        cursor position
  754.  * mouseRgn:    mouse region
  755.  *
  756.  */
  757.  
  758. void    CTermPane::AdjustCursor(Point where,RgnHandle mouseRgn)    
  759. {
  760.     /* The cursor shape is updated by the tool during the idle time */
  761.  
  762. }
  763.  
  764.  
  765. /* ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ */
  766.  
  767. /*
  768.  * Activate
  769.  *
  770.  * Terminal pane activating
  771.  *
  772.  */
  773.  
  774. void CTermPane::Activate(void)
  775. {
  776.     Boolean        wasActive = reallyActive;
  777.     long        selStart = itsSelStart;
  778.     long        selEnd = itsSelEnd;
  779.     
  780.     /* Remove the outlined selection range. */
  781.     
  782.     if (!wasActive)
  783.     {
  784.         Prepare();
  785.         if (selStart != selEnd)
  786.             HiliteTextRange(selStart, selEnd);
  787.     }
  788.     
  789.     inherited::Activate();        /* Pass message to its superclass    */
  790.     
  791.     Prepare();
  792.  
  793.     TMActivate(itsTerm,TRUE);        /* Tool activation */
  794.     
  795.     /* Reset our instance variables */
  796.     
  797.     reallyActive = TRUE;
  798.     
  799.     /* Hilite the now active selection range, if appropriate */
  800.     
  801.     if (selStart != selEnd && !wasActive)
  802.     {
  803.         Prepare();
  804.         HiliteTextRange(selStart, selEnd);
  805.     }
  806. }    
  807.  
  808.  
  809. /* ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ */
  810.  
  811. /*
  812.  * Deactivate
  813.  *
  814.  * Terminal pane deactivation
  815.  *
  816.  */
  817.  
  818. void CTermPane::Deactivate(void)
  819. {
  820.     Boolean        wasActive = reallyActive;
  821.     long        selStart = itsSelStart;
  822.     long        selEnd = itsSelEnd;
  823.     
  824.     /* Unhilite the selection range. */
  825.     
  826.     if (wasActive)
  827.     {
  828.         Prepare();
  829.         if (selStart != selEnd)
  830.             HiliteTextRange(selStart, selEnd);
  831.     }
  832.     
  833.     /* Reset our instance variables */
  834.     
  835.     reallyActive = FALSE;
  836.     
  837.     Prepare();
  838.  
  839.     TMActivate(itsTerm,FALSE);        /* tool deactivation */
  840.     
  841.     inherited::Deactivate();        /* Pass message to its superclass */
  842.     
  843.     /* Outline the now inactive selection range, if appropriate */
  844.     
  845.     if (wasActive)
  846.     {
  847.         Prepare();
  848.         if (selStart != selEnd)
  849.             HiliteTextRange(selStart, selEnd);
  850.     }
  851. }    
  852.  
  853.  
  854. /* ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ */
  855.  
  856. /*
  857.  * Mouse clic in the terminal pane
  858.  *
  859.  * hitPt:            Click position
  860.  * modifierKeys:    Keyboard stat
  861.  * when:            click instant
  862.  *
  863.  */
  864.  
  865. void CTermPane::DoClick(Point hitPt,short modifierKeys,long when)
  866. {
  867.     EventRecord        theEvent;
  868.     LongPt            framePt;
  869.     TermEnvironRec    theEnvirons;
  870.     long            charOffset;
  871.     long            selStart, selEnd;
  872.     
  873.     /* Get the current selection range */
  874.     
  875.     selStart = itsSelStart;
  876.     selEnd = itsSelEnd;
  877.     
  878.     /* Determine which character was clicked on */
  879.     GetEnvirons(&theEnvirons);
  880.     
  881.     QDToFrame(hitPt, &framePt);
  882.     framePt.v += position.v * theEnvirons.cellSize.v;
  883.     framePt.h += position.h * theEnvirons.cellSize.h;
  884.     
  885.     charOffset = GetCharOffset(&framePt);
  886.     origCharOffset = lastCharOffset = charOffset;
  887.     
  888.     if (gClicks == 1)
  889.     {
  890.         // If the Shift key is down, extend the selection.
  891.         
  892.         if (modifierKeys & shiftKey)
  893.             origCharOffset = lastCharOffset = itsSelAnchor;
  894.         else
  895.             SetSelection(charOffset, charOffset, kRedraw);    
  896.     }
  897.     else if (gClicks == 2)
  898.     {
  899.         // select current word.
  900.         
  901.         selStart = CalcWordBreak(charOffset, kBreakLeft);
  902.         selEnd = CalcWordBreak(charOffset, kBreakRight);
  903.         
  904.         SetSelection(selStart, selEnd, kRedraw);
  905.     }
  906.     else    // select the entire line.
  907.     {
  908.         long            line;
  909.         short            vertInset, horzInset;
  910.         TermEnvironRec    theEnvirons;
  911.             
  912.         GetEnvirons(&theEnvirons);
  913.  
  914.         vertInset = theEnvirons.slop.v;
  915.         horzInset = theEnvirons.slop.h;
  916.         
  917.         line = (framePt.v - vertInset) / theEnvirons.cellSize.v;
  918.         
  919.         if (line >= numCachedLines)
  920.         {
  921.             long    auxOffset = theEnvirons.auxSpace.top / theEnvirons.cellSize.v;
  922.             
  923.             vertInset = theEnvirons.slop.v + theEnvirons.auxSpace.top;
  924.             horzInset = theEnvirons.slop.h + theEnvirons.auxSpace.left;
  925.         
  926.             line = Max(((framePt.v - vertInset) / theEnvirons.cellSize.v), numCachedLines);
  927.         }
  928.         
  929.         selStart = GetLineStart(line);
  930.         selEnd = GetLineEnd(line);
  931.         
  932.         if (itsSelStart != itsSelEnd && selStart < itsSelStart && selEnd > itsSelEnd)
  933.         {
  934.             HiliteTextRange(selStart, itsSelStart);
  935.             HiliteTextRange(itsSelEnd, selEnd);
  936.             SetSelection(selStart, selEnd, kNoRedraw);
  937.         }
  938.         else if (selStart != itsSelStart || selEnd != itsSelEnd)
  939.             SetSelection(selStart, selEnd, kRedraw);
  940.             
  941.         origLine = lastLine = line;
  942.     }
  943.  
  944.     theEvent.what = mouseDown;        
  945.     theEvent.where = hitPt;
  946.     LocalToGlobal(&theEvent.where);        /* Conversion */
  947.     theEvent.modifiers = modifierKeys;
  948.     theEvent.when = when;
  949.     
  950.     TMClick(itsTerm,&theEvent);        /* Tool handles clicks… */
  951.     
  952.     gLastMouseUp.what = mouseUp;    /* MouseUp… simulation */
  953.     gLastMouseUp.when = TickCount();
  954.     gLastMouseUp.where = hitPt;
  955.     LocalToGlobal( &gLastMouseUp.where);    /* Conversion */
  956.     gLastMouseUp.modifiers = modifierKeys;
  957.     
  958.     /* Determine the anchor point for the selection */
  959.     
  960.     if (gClicks == 1)
  961.         itsSelAnchor = origCharOffset;
  962.     else if (gClicks == 2)
  963.         itsSelAnchor = CalcWordBreak(origCharOffset, charOffset < origCharOffset ? kBreakRight : kBreakLeft);
  964.     else
  965.         itsSelAnchor = (charOffset < origCharOffset ? GetLineEnd(origLine) : GetLineStart(origLine));
  966.         
  967.     /* Notify our dependents that the selection has changed */
  968.     
  969.     SelectionChanged();
  970. }
  971.  
  972.  
  973. /* ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ */
  974.  
  975. /*
  976.  * ResizeFrame
  977.  *
  978.  * Handle changing of the terminal pane size
  979.  *
  980.  * delta:    updates rect
  981.  *
  982.  */
  983.  
  984. void CTermPane::ResizeFrame(Rect *delta)
  985. {
  986.     Rect        newTermRect;
  987.     
  988.     inherited::ResizeFrame(delta);            /* Pass message to its superclass */
  989.     
  990.     //FrameToWindR(&frame,&newTermRect);
  991.     LongToQDRect(&frame,&newTermRect);        /* Visible region */
  992.     
  993.     TMResize(itsTerm,&newTermRect);         /* tool handles resizing… */
  994.     
  995.                                             /* Border gets cleaned up in Draw method */
  996. }
  997.  
  998. /* ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ */
  999.  
  1000. /*
  1001.  * DoKeyDown
  1002.  *
  1003.  * Keyboard handling
  1004.  *
  1005.  * theChar:        Typed char
  1006.  * keyCode:        Code of the corresponding key
  1007.  * macEvent:    Pointer on the related event
  1008.  *
  1009.  */
  1010.  
  1011. void CTermPane::DoKeyDown(char theChar,Byte keyCode,EventRecord    *macEvent)
  1012. {
  1013.     TMKey(itsTerm,macEvent);        /* Tool handles keys… */
  1014.     
  1015. }    
  1016.  
  1017. /* ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ */
  1018.  
  1019. /*
  1020.  * DoAutoKey
  1021.  *
  1022.  * Key repetition
  1023.  *
  1024.  * theChar:        typed char
  1025.  * keyCode:        code of the related code
  1026.  * macEvent:    Pointer on the corresponding event
  1027.  *
  1028.  */
  1029.  
  1030. void CTermPane::DoAutoKey(char theChar,Byte keyCode,EventRecord    *macEvent)
  1031. {
  1032.     this->DoKeyDown(theChar,keyCode,macEvent);    
  1033. }    
  1034.  
  1035.  
  1036. /* ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ */
  1037.  
  1038. /*
  1039.  * SetConfig
  1040.  *
  1041.  * Terminal tool configuration
  1042.  *
  1043.  * theConfig:    configuration C string
  1044.  *
  1045.  * Return:        Negative value: error (-1 -> unknown)
  1046.  *                Positive value: Parser stop index
  1047.  *                tmNoErr if all is OK
  1048.  *
  1049.  */
  1050.  
  1051. short CTermPane::SetConfig(char *theConfig)
  1052. {
  1053.     short retCode;
  1054.     
  1055.     retCode = TMSetConfig(itsTerm,theConfig);
  1056.     
  1057.     this->changedConfig();    /* Config update */
  1058.     
  1059.     return retCode;
  1060. }    
  1061.  
  1062.  
  1063. /* ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ */
  1064.  
  1065. /*
  1066.  * GetToolName
  1067.  *
  1068.  * Return the name of the current tool
  1069.  *
  1070.  * toolName:    name of the current tool (pascal string)
  1071.  *
  1072.  */
  1073.  
  1074. void CTermPane::GetToolName(Str63 toolName)
  1075. {
  1076.     SignedByte    savedState;
  1077.     
  1078.     savedState = HGetState((Handle)itsTerm);
  1079.     HLock((Handle)itsTerm);
  1080.     
  1081.     TMGetToolName((*itsTerm)->procID,toolName);
  1082.     
  1083.     HSetState((Handle)itsTerm, savedState);
  1084. }    
  1085.  
  1086.  
  1087. /* ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ */
  1088.  
  1089. /*
  1090.  * GetConfig
  1091.  *
  1092.  * Return the configuration string of the current tool
  1093.  *
  1094.  * Reeturn a pointer on the C string
  1095.  *
  1096.  */
  1097.  
  1098. Ptr CTermPane::GetConfig(void)
  1099. {
  1100.     return(TMGetConfig(itsTerm));
  1101. }    
  1102.  
  1103.  
  1104. /* ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ */
  1105.  
  1106. /*
  1107.  * DoMenu
  1108.  *
  1109.  * Terminal tool menus handling
  1110.  *
  1111.  * theMenu:    selected menu
  1112.  * theItem:    selected item
  1113.  *
  1114.  * Return TRUE if the menu belongs to the tool
  1115.  *
  1116.  */
  1117.  
  1118. Boolean CTermPane::DoMenu(short theMenu,short theItem)
  1119. {
  1120.     return(TMMenu(itsTerm,theMenu,theItem));
  1121. }    
  1122.  
  1123.  
  1124. /* ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ */
  1125.  
  1126. /*
  1127.  * DoEvent
  1128.  *
  1129.  * Terminal tool related events
  1130.  *
  1131.  * theEvent:    Pointeur on the event
  1132.  * theWindow:    Window associated with the event
  1133.  *
  1134.  * Return TRUE if it is a tool event
  1135.  *
  1136.  */
  1137.  
  1138. Boolean CTermPane::DoEvent(EventRecord *theEvent,WindowPtr theWindow)
  1139. {
  1140.     Boolean        isToolEvent;
  1141.     TermHandle    theTerm;
  1142.     
  1143.     isToolEvent = FALSE;
  1144.     
  1145.     theTerm = (TermHandle) GetWRefCon(theWindow);
  1146.     
  1147.     if (theTerm == itsTerm)    {            /* Tool window ? */
  1148.         TMEvent(itsTerm,theEvent);
  1149.         isToolEvent = TRUE;
  1150.     }
  1151.     
  1152.     return isToolEvent;
  1153. }    
  1154.  
  1155.  
  1156. /* ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ */
  1157.  
  1158. /*
  1159.  * GetTermHandle
  1160.  *
  1161.  * Return a Handle on the current terminal record
  1162.  *
  1163.  * Return the Handle
  1164.  *
  1165.  */
  1166.  
  1167. TermHandle CTermPane::GetTermHandle(void)
  1168. {
  1169.     return(itsTerm);
  1170. }    
  1171.  
  1172.  
  1173. /* ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ */
  1174.  
  1175. /*
  1176.  * DoStream
  1177.  *
  1178.  * Received data handling
  1179.  *
  1180.  * buffer:        Receiving buffer
  1181.  * buffSize:    buffer size
  1182.  * flags:        end of message
  1183.  *
  1184.  * Return the nb of chars handled
  1185.  *
  1186.  */
  1187.  
  1188. long CTermPane::DoStream(Ptr buffer,long buffSize,CMFlags flags)
  1189. {
  1190.     long    numLinesScrolled, numBytes;
  1191.     
  1192.     Prepare();
  1193.     
  1194.     numBytes = TMStream(itsTerm,buffer,buffSize,flags);
  1195.  
  1196.     // scroll to new line
  1197.     numLinesScrolled = LinesScrolledUp() + LinesScrolledDown();
  1198.     
  1199.     if (numLinesScrolled)
  1200.     {
  1201.         LongPt    curPos;
  1202.         
  1203.         GetPosition(&curPos);
  1204.         curPos.v += numLinesScrolled;
  1205.         
  1206.         ScrollTo(&curPos, false);
  1207.         
  1208.         Prepare();
  1209.     }
  1210.     
  1211.     return numBytes;
  1212. }    
  1213.  
  1214.  
  1215. /* ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ */
  1216.  
  1217. /*
  1218.  * TermClear
  1219.  *
  1220.  * Clear out the terminal pane, reset to origin.
  1221.  *
  1222.  */
  1223.  
  1224. void CTermPane::TermClear(void)
  1225. {    
  1226.     Rect        termRect, viewRect;
  1227.     LongRect    theLongArea;
  1228.     
  1229.     Prepare();
  1230.  
  1231.     TMClear(itsTerm);
  1232.     
  1233.     // remove cached lines.
  1234.     numCachedLines = 0;
  1235.     position.v = 0;
  1236.     
  1237.     itsScrollBuffer->Truncate();
  1238.  
  1239.     // scroll TM back to origin.
  1240.     viewRect = (*itsTerm)->viewRect;
  1241.     termRect = (*itsTerm)->termRect;
  1242.         
  1243.     ScrollTerminal(termRect.left - viewRect.left,(termRect.top - viewRect.top) + topMargin);
  1244.         
  1245.     AdjustBounds();
  1246.     
  1247.     // erase the whole frame
  1248.     GetFrame(&theLongArea);
  1249.     FrameToQDR(&theLongArea,&termRect);
  1250.     
  1251.     termRect.bottom = termRect.top + height;
  1252.     EraseRect(&termRect);
  1253. }    
  1254.  
  1255.  
  1256. /* ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ */
  1257.  
  1258. /*
  1259.  * Reset
  1260.  *
  1261.  * Terminal reset
  1262.  *
  1263.  */
  1264.  
  1265. void CTermPane::Reset(void)
  1266. {
  1267.     short    response;
  1268.     
  1269.     PositionDialog('ALRT', RESET_ALRT_ID);
  1270.     
  1271.     InitCursor();
  1272.     
  1273.     response = Alert(RESET_ALRT_ID, NULL);
  1274.         
  1275.     if (response == answerNO)    {
  1276.         Prepare();
  1277.     
  1278.         TMReset(itsTerm);
  1279.         
  1280.         this->changedConfig();    /* Configuration update */
  1281.     }
  1282.  
  1283. }    
  1284.  
  1285.  
  1286. /* ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ */
  1287.  
  1288. /*
  1289.  * DoTabCopy
  1290.  *
  1291.  * Table copy
  1292.  *
  1293.  */
  1294.  
  1295. void CTermPane::DoTabCopy(void)
  1296. {
  1297.     DoCopy(kTabCopy);
  1298. }    
  1299.  
  1300. /* ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ */
  1301.  
  1302. /*
  1303.  * GetExtent
  1304.  *
  1305.  * Return the size (in char rows and columns) of the terminal pane
  1306.  *
  1307.  * theHExtent:    Nb of columns
  1308.  * theVExtent:    Nb of rows
  1309.  *
  1310.  */
  1311.  
  1312. void CTermPane::GetExtent(long *theHExtent,long *theVExtent)
  1313. {
  1314.     GetTermExtent(theHExtent,theVExtent);
  1315.     
  1316.     *theVExtent = GetNumLines();
  1317. }
  1318.  
  1319.  
  1320. /* ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ */
  1321.  
  1322. /*
  1323.  * GetEnvirons
  1324.  *
  1325.  * Terminal parameters
  1326.  *
  1327.  * theEnvirons:        Pointer on the environment record
  1328.  *
  1329.  * Return an error code
  1330.  *
  1331.  */
  1332.  
  1333. OSErr CTermPane::GetEnvirons(TermEnvironRec *theEnvirons)
  1334. {
  1335.     theEnvirons->version = curTermEnvRecVers;/* Record version */
  1336.  
  1337.     return (TMGetTermEnvirons(itsTerm,theEnvirons));    
  1338. }    
  1339.  
  1340.  
  1341. /* ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ */
  1342.  
  1343. /*
  1344.  * GetLine
  1345.  *
  1346.  * Content of a terminal screen line
  1347.  *
  1348.  * lineNo:        line number
  1349.  * theTermData:    Pointer on the content of the line
  1350.  *
  1351.  * Renturn an error code
  1352.  *
  1353.  */
  1354.  
  1355. void CTermPane::GetLine(short lineNo,TermDataBlock *theTermData)
  1356. {
  1357.     theTermData->theData = NewHandleCanFail(0);
  1358.     
  1359.     TMGetLine(itsTerm,lineNo,theTermData);    
  1360. }    
  1361.  
  1362.  
  1363. /* ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ */
  1364.  
  1365. /*
  1366.  * Scroll
  1367.  *
  1368.  * Terminal pane scrolling
  1369.  *
  1370.  * hDelta:    Horizontal scrolling
  1371.  * vDelta:    vertical scrolling
  1372.  * redraw:    flag of redrawing
  1373.  *
  1374.  */
  1375.  
  1376. void CTermPane::Scroll(long hDelta,long vDelta,Boolean redraw)
  1377. {
  1378.     long            hPixels,vPixels;
  1379.     TermEnvironRec    theEnvirons;
  1380.     
  1381.     Prepare();
  1382.     
  1383.     GetEnvirons(&theEnvirons);
  1384.     
  1385.     hPixels = hDelta * hScale;
  1386.     vPixels = vDelta * vScale;
  1387.     
  1388.     /*    even if we scroll more than a screen worth's, execute TMScroll or the viewRect
  1389.         will not be recalculated  by TM */
  1390.         
  1391.     // if going down, scroll terminal before scrollback buffer
  1392.     if (vDelta <= 0)
  1393.         ScrollTerminal(-(hPixels),-(vPixels));
  1394.     
  1395.     if ((Abs(hPixels) < width) && (Abs(vPixels) < height))
  1396.     {
  1397.         Rect        termRect, viewRect, visRect;
  1398.         RgnHandle    termRgn, visRgn, cacheRgn;
  1399.             
  1400.         GetEnvirons(&theEnvirons);
  1401.         
  1402.         // calculate the visible cache and invalidate it.
  1403.         termRgn = NewRgn();
  1404.         visRgn = NewRgn();
  1405.         cacheRgn = NewRgn();
  1406.         
  1407.         // let cache line write through 'border' of terminal region
  1408.         viewRect = (*itsTerm)->viewRect;        
  1409.         termRect = (*itsTerm)->termRect;
  1410.         
  1411.         SectRect(&termRect, &viewRect, &visRect);
  1412.         
  1413.         RectRgn(termRgn,&termRect);
  1414.         RectRgn(visRgn,&visRect);
  1415.         DiffRgn(termRgn,visRgn,cacheRgn);
  1416.         
  1417.         RgnRect(cacheRgn,&visRect);
  1418.         OffsetRect(&visRect,0,topMargin - TERMINAL_OFFSET);
  1419.         
  1420.         int numVisCacheLines = RectHeight(&visRect) / theEnvirons.cellSize.v;
  1421.         
  1422.         if (numVisCacheLines - abs(vDelta) >= 1)
  1423.         {
  1424.             short    numVisTermLines, newHeight;
  1425.                         
  1426.             // don't dovetail the bottom of cache region on terminal region
  1427.             if (RectHeight(&visRect) >= topMargin)
  1428.                 visRect.bottom -= topMargin;
  1429.             
  1430.             // only scroll an integral number of lines.
  1431.             newHeight = (RectHeight(&visRect) / theEnvirons.cellSize.v) * theEnvirons.cellSize.v;
  1432.             visRect.bottom = Min(visRect.bottom,visRect.top + newHeight);
  1433.             
  1434.             // check for frame off by one
  1435.             GetTermRect(&termRect);
  1436.  
  1437.             numVisTermLines = RectHeight(&termRect) / theEnvirons.cellSize.v;
  1438.             
  1439.             ScrollRect(&visRect,-(hPixels),-(vPixels),cacheRgn);
  1440.         }
  1441.         
  1442.         InvalRgn(cacheRgn);
  1443.         
  1444.         DisposeRgn(termRgn);
  1445.         DisposeRgn(visRgn);
  1446.         DisposeRgn(cacheRgn);
  1447.     }
  1448.     else
  1449.         Refresh();
  1450.         
  1451.     // if going up, scroll terminal after scrollback buffer
  1452.     if (vDelta > 0)
  1453.         ScrollTerminal(-(hPixels),-(vPixels));
  1454.         
  1455.     position.h += hDelta;
  1456.     position.v += vDelta;
  1457.     
  1458.     AdjustBounds();
  1459.     
  1460.     if (redraw)
  1461.         ((CWindow *) (((WindowPeek) macPort)->refCon))->Update();
  1462. }
  1463.  
  1464.  
  1465. /* ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ */
  1466.  
  1467. /*
  1468.  * changedConfig
  1469.  *
  1470.  * Terminal tool configuration update
  1471.  *
  1472.  */
  1473.  
  1474. void CTermPane::changedConfig(Boolean doBroadcast)
  1475. {
  1476.     TermEnvironRec    theEnvirons;
  1477.     Rect            viewRect;
  1478.     LongRect        newBounds;
  1479.     SignedByte        savedState;
  1480.     
  1481.     //savedState = HGetState((Handle)itsTerm);
  1482.     //HLock((Handle)itsTerm);
  1483.     
  1484.     GetEnvirons(&theEnvirons);                            /* Environment */
  1485.     
  1486.     hScale = theEnvirons.cellSize.h;                    /* Chars size */
  1487.     vScale = theEnvirons.cellSize.v;
  1488.     
  1489.     topMargin = (theEnvirons.cellSize.v / 3) + TERMINAL_OFFSET;
  1490.  
  1491.     SetTermOffset();
  1492.     
  1493.     AdjustBounds();
  1494.     
  1495.     if (doBroadcast)
  1496.         BroadcastChange(termSizeChangedInd, NULL);        /* tell the supervisor */
  1497.     
  1498.     //HSetState((Handle)itsTerm,savedState);
  1499. }    
  1500.  
  1501.  
  1502. /* ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ */
  1503.  
  1504. /*
  1505.  * DoSelectAll
  1506.  *
  1507.  * Complete selection
  1508.  *
  1509.  */
  1510.  
  1511. void CTermPane::DoSelectAll(void)
  1512. {
  1513.     Prepare();
  1514.     
  1515.     long termTextLen = TerminalTextLength(-1,-1);
  1516.     
  1517.     if (termTextLen)
  1518.     {
  1519.         TermEnvironRec    theEnvirons;
  1520.         TMSelection        newSelection;
  1521.         TMSelTypes        newSelType;
  1522.         long            numRows,numCols;
  1523.     
  1524.         GetEnvirons(&theEnvirons);        /* Environment */
  1525.         
  1526.         numCols = termTextLen % theEnvirons.textCols;
  1527.         numRows = (termTextLen / theEnvirons.textCols) + ((numCols) ? 1 : 0);
  1528.     
  1529.         SetRect(&(newSelection.selRect),1,1,numCols,numRows);
  1530.     
  1531.         newSelType = selTextNormal;
  1532.     
  1533.         TMSetSelection(itsTerm,&newSelection,newSelType);
  1534.     }
  1535.     
  1536.     SetSelection(0, GetLength(), kRedraw);
  1537. }    
  1538.  
  1539. /* ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ */
  1540.  
  1541. /*
  1542.  * BindConnection
  1543.  *
  1544.  * Give terminal a connection object
  1545.  *
  1546.  */
  1547.  
  1548. void CTermPane::BindConnection(CConnection *newConnection)
  1549. {
  1550.  itsConnection = newConnection;
  1551. }
  1552.  
  1553. /* ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ */
  1554.  
  1555. /*
  1556.  * GetConnection
  1557.  *
  1558.  * return connection object
  1559.  *
  1560.  */
  1561.  
  1562. CConnection    *CTermPane::GetConnection(void)
  1563. {
  1564.  return itsConnection;
  1565. }
  1566.  
  1567. /* ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ */
  1568.  
  1569. /*
  1570.  * GetFileTransfer
  1571.  *
  1572.  * return file transfer object
  1573.  *
  1574.  */
  1575.  
  1576. CFileTransfer *CTermPane::GetFileTransfer(void)
  1577. {
  1578.  return itsFileTransfer;
  1579. }
  1580.  
  1581. /* ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ */
  1582.  
  1583. /*
  1584.  * default environment call-back proc
  1585.  *
  1586.  * 
  1587.  *
  1588.  */
  1589.  
  1590. pascal CMErr CTermPane::DefEnvironsProc (long refCon, ConnEnvironRecPtr theEnvPtr)
  1591. {
  1592.  CTermPane *theTermPane = (CTermPane *)refCon;
  1593.  CConnection *theConnection = theTermPane->GetConnection();
  1594.  
  1595.  return theConnection->GetEnvirons(theEnvPtr);
  1596. }
  1597.  
  1598. /* ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ */
  1599.  
  1600. /*
  1601.  * default send call-back proc
  1602.  *
  1603.  * 
  1604.  *
  1605.  */
  1606.  
  1607. pascal long CTermPane::DefSendProc (Ptr buffPtr, long howMany, long refCon, CMFlags flags)
  1608. {
  1609.  OSErr            myErr = 0;
  1610.  CTermPane        *theTermPane = (CTermPane *)refCon;
  1611.  CConnection    *theConnection = theTermPane->GetConnection();
  1612.  CFileTransfer    *itsFileTransfer = theTermPane->GetFileTransfer();
  1613.   
  1614.  if (theConnection->GetConnHandle())
  1615.  {
  1616.     // If there's a file transfer in progress && it's     
  1617.     // over our connection, then don't send the data.    
  1618.     
  1619.     if (itsFileTransfer && itsFileTransfer->IsRunningOnSameCircuit ())
  1620.         howMany = 0;
  1621.     else
  1622.         myErr = theConnection->DataWrite(buffPtr,&howMany,false,nil,15,flags);
  1623.  }
  1624.  else howMany = 0;
  1625.  
  1626.  return howMany;
  1627. }
  1628.  
  1629. /* ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ */
  1630.  
  1631. /*
  1632.  * default Break call-back proc
  1633.  *
  1634.  * 
  1635.  *
  1636.  */
  1637.  
  1638. pascal void CTermPane::DefBreakProc (long duration, long refCon)
  1639. {
  1640.  CTermPane *theTermPane = (CTermPane *)refCon;
  1641.  CConnection *theConnection = theTermPane->GetConnection();
  1642.  
  1643.  theConnection->SendBreak();
  1644. }
  1645.  
  1646. /*******************************************************************
  1647. *    DefReadCompletedProc    - default async read completor proc
  1648. *
  1649. *        theConn                - which connection tool found it
  1650. *
  1651. **********************************************************************/
  1652.  
  1653. pascal void CTermPane::DefReadCompletedProc (ConnHandle myConn)
  1654. {
  1655.  CConnection *theConnection = (CConnection *)CMGetRefCon (myConn);
  1656.                            
  1657.  // if we belong to a terminal pane, get its file transfer object
  1658.  if (member(theConnection->itsSupervisor, CTermPane))
  1659.  {
  1660.     Boolean    wasLocked;
  1661.      CTermPane *theTermPane = (CTermPane *)theConnection->itsSupervisor;
  1662.  
  1663.      wasLocked = theTermPane->Lock(true);
  1664.      
  1665.     theTermPane->asyncErr = (**myConn).errCode;
  1666.     theTermPane->readAmount = ((**myConn).asyncCount[cmDataIn] < (IOBUFSIZE-1L)) ?
  1667.                                  (**myConn).asyncCount[cmDataIn] : (IOBUFSIZE-1L);
  1668.                                                              
  1669.     theTermPane->readCompleted = true;
  1670.      theTermPane->Lock(wasLocked);
  1671.  }
  1672. }    
  1673.  
  1674. /*******************************************************************
  1675. *    DefCacheProc    - default line cache procedure
  1676. *
  1677. *        refCon                - user defined, points to the term object
  1678. *        theTermData            - contains data to be cached.
  1679. *
  1680. **********************************************************************/
  1681.  
  1682. pascal long CTermPane::DefCacheProc (long refCon, TermDataBlock *theTermData)
  1683. {
  1684.  CTermPane    *theTermPane = (CTermPane *)refCon;
  1685.  Boolean    wasLocked;
  1686.  long        sizeCached = 0L;
  1687.  
  1688.  wasLocked = theTermPane->Lock(true);    // we're going to use instance variables in ToolBox routines.
  1689.  
  1690.  HLock(theTermData->theData);
  1691.  
  1692.  if (theTermData->flags == tmTextTerminal)
  1693.  {
  1694.      char    *cacheLine = (char *)*(theTermData->theData);
  1695.           
  1696.      if (theTermPane->numCachedLines < theTermPane->itsScrollBuffer->GetMaxLines())
  1697.      {
  1698.          theTermPane->itsScrollBuffer->AddLine(cacheLine, GetHandleSize(theTermData->theData));
  1699.          
  1700.         theTermPane->numCachedLines++;
  1701.         theTermPane->position.v++;
  1702.         
  1703.         theTermPane->AdjustBounds();
  1704.     
  1705.         theTermPane->Prepare();
  1706.      }
  1707.      else
  1708.      {
  1709.          theTermPane->itsScrollBuffer->DeleteLine(0);
  1710.          theTermPane->itsScrollBuffer->AddLine(cacheLine, GetHandleSize(theTermData->theData));
  1711.      }
  1712.  
  1713.  }
  1714.  
  1715.  HUnlock(theTermData->theData);
  1716.  
  1717.  theTermPane->Lock(wasLocked);
  1718.  
  1719.  return sizeCached;
  1720. }
  1721.  
  1722. /*******************************************************************
  1723. *    DefClikLoop    - default mouse click procedure
  1724. *
  1725. *        refCon    - user defined, points to the term object
  1726. *
  1727. **********************************************************************/
  1728.  
  1729. pascal Boolean    CTermPane::DefClikLoop (long refCon)
  1730. {
  1731.     Boolean        inCacheRegion = true;
  1732.     Point        hitPt;
  1733.     CTermPane    *theTermPane = (CTermPane *)refCon;
  1734.     
  1735.     GetMouse(&hitPt);
  1736.     
  1737.     if (StillDown())
  1738.     {
  1739.         inCacheRegion = theTermPane->ProcessCacheClick(hitPt);
  1740.     }
  1741.     else
  1742.     {
  1743.         LongPt        framePt;
  1744.         long        charOffset;
  1745.     
  1746.         theTermPane->QDToFrame(hitPt, &framePt);
  1747.         PinInRect(&(theTermPane->frame), &framePt);
  1748.     
  1749.         charOffset = theTermPane->GetCharOffset(&framePt);
  1750.         inCacheRegion = charOffset < theTermPane->itsScrollBuffer->GetTextLength();
  1751.     }
  1752.     
  1753.     return inCacheRegion;
  1754. }
  1755.     
  1756. /* ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ */
  1757.  
  1758. /*
  1759.  * GetCursor -    Get the cursor position. 
  1760.  *
  1761.  * 
  1762.  *
  1763.  */
  1764.  
  1765. Point CTermPane::GetCursor(TMCursorTypes curType)
  1766. {
  1767.  return TMGetCursor(itsTerm, curType);
  1768. }
  1769.  
  1770. // member function overrides
  1771.  
  1772. /* ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ */
  1773.  
  1774. /*
  1775.  * Prepare -    Prepare the terminal for drawing. Clips to actual terminal
  1776.  *                area
  1777.  * 
  1778.  *
  1779.  */
  1780.  
  1781. void    CTermPane::Prepare( void)
  1782. {
  1783.     inherited::Prepare();
  1784. }
  1785.  
  1786. /******************************************************************************
  1787.  SetWholeLines
  1788.  
  1789.         Specify whether or not the frame should be adjusted so that
  1790.         lines are not cut off vertically. The Pane is NOT redrawn.
  1791.         
  1792.  ******************************************************************************/
  1793.  
  1794. void    CTermPane::SetWholeLines( Boolean aWholeLines)
  1795. {
  1796.     Rect        newFrame;
  1797.               
  1798.     inherited::SetWholeLines(aWholeLines);
  1799.     
  1800.     if (wholeLines && fixedLineHeights)
  1801.     {
  1802.         LongToQDRect(&frame,&newFrame);            // get new frame as true measure of line heights.
  1803.         newFrame.bottom = newFrame.top + height;
  1804.         
  1805.         CalcTermRect(&newFrame);
  1806.         
  1807.         // use the height of the first line as the standard height
  1808.             
  1809.         short lineHeight = Get1Height(1);    
  1810.             
  1811.         if (lineHeight > 0)
  1812.         {
  1813.             frame.bottom = frame.top + (lineHeight * ((RectHeight(&newFrame) - topMargin) / lineHeight)) + topMargin;
  1814.             frame.bottom--;
  1815.         }
  1816.             
  1817.         SetRect(&newFrame,0,0,0,0);
  1818.         CalcFullRect(&newFrame);
  1819.         
  1820.         frame.bottom += newFrame.bottom;
  1821.         //frame.right += newFrame.right;
  1822.         
  1823.         CalcAperture();
  1824.     }
  1825.  
  1826. }
  1827.  
  1828. void    CTermPane::SetTextPtr(Ptr textPtr, long numChars)
  1829. {
  1830. }
  1831.  
  1832. Handle    CTermPane::GetTextHandle(void)
  1833. {
  1834.     return itsScrollBuffer->GetTextHandle();
  1835. }
  1836.  
  1837. void    CTermPane::SetFontNumber(short aFontNumber)
  1838. {
  1839. }
  1840.  
  1841. /*void    CTermPane::SetFontName(Str255 aFontName)
  1842. {
  1843. }*/
  1844.  
  1845. void    CTermPane::SetFontStyle(short aStyle)
  1846. {
  1847. }
  1848.  
  1849. void    CTermPane::SetFontSize(short aSize)
  1850. {
  1851. }
  1852.  
  1853. void    CTermPane::SetTextMode(short aMode)
  1854. {
  1855. }
  1856.  
  1857. void    CTermPane::SetAlignCmd(long anAlignment)
  1858. {
  1859. }
  1860.  
  1861. long    CTermPane::GetAlignCmd( void)
  1862. {
  1863.     return 0L;
  1864. }
  1865.  
  1866. void    CTermPane::SetSpacingCmd(long aSpacingCmd)
  1867. {
  1868. }
  1869.  
  1870. /******************************************************************************
  1871.  GetHeight (OVERRIDE)
  1872.  
  1873.     Return the height of the indicated lines of text
  1874.  ******************************************************************************/
  1875.  
  1876. long    CTermPane::GetHeight( long startLine, long endLine)
  1877. {
  1878.     TermEnvironRec    theEnvirons;
  1879.     
  1880.     GetEnvirons(&theEnvirons);
  1881.     
  1882.     return (long)((endLine - startLine + 1) * theEnvirons.cellSize.v);
  1883. }
  1884.  
  1885. /******************************************************************************
  1886.  GetCharOffset (OVERRIDE)
  1887.  
  1888.         Return the offset into the text buffer of the character position
  1889.         at a point in Frame coordinates.
  1890.         
  1891.  ******************************************************************************/
  1892.  
  1893. long    CTermPane::GetCharOffset( LongPt *aPt)
  1894. {
  1895.     long    line, charOffset = 0L;
  1896.     long    numTermLines;
  1897.     short    vertInset, horzInset, lineLen;
  1898.  
  1899.     TermEnvironRec    theEnvirons;
  1900.  
  1901.     GetEnvirons(&theEnvirons);
  1902.  
  1903.     lineLen = theEnvirons.cellSize.h * theEnvirons.textCols;
  1904.     
  1905.     // line that has the desired character.
  1906.     vertInset = theEnvirons.slop.v;
  1907.     horzInset = theEnvirons.slop.h;
  1908.     
  1909.     line = (aPt->v - vertInset) / theEnvirons.cellSize.v;
  1910.     
  1911.     if (line >= numCachedLines)
  1912.     {
  1913.         long    auxOffset = theEnvirons.auxSpace.top / theEnvirons.cellSize.v;
  1914.         
  1915.         vertInset = theEnvirons.slop.v + theEnvirons.auxSpace.top;
  1916.         horzInset = theEnvirons.slop.h + theEnvirons.auxSpace.left;
  1917.         
  1918.         line = Max(((aPt->v - vertInset) / theEnvirons.cellSize.v), numCachedLines);
  1919.     }
  1920.  
  1921.     if (line >= 0)
  1922.     {
  1923.         // number of lines in the actual terminal
  1924.         numTermLines = GetCursor().v - 1;
  1925.  
  1926.         // if beyond end of buffer, return the last character
  1927.         if (line > (numTermLines + itsScrollBuffer->GetNumLines()) - 1)
  1928.         {
  1929.             // last character is the terminal buffer and scrollback buffer.
  1930.             charOffset = GetLength();
  1931.         }
  1932.         else
  1933.         {
  1934.             long lineOffset = 0L;
  1935.             
  1936.             // calculate number of characters in line containing point
  1937.             if (aPt->h > horzInset)
  1938.             {
  1939.                 long hPos = aPt->h;
  1940.                 
  1941.                 // adjust if clicked in right margin.
  1942.                 if (hPos > (lineLen + horzInset))
  1943.                     hPos = lineLen + horzInset;
  1944.                     
  1945.                 lineOffset = (hPos - horzInset) / theEnvirons.cellSize.h;
  1946.                 
  1947.                 if (((hPos - horzInset) % theEnvirons.cellSize.h) >= theEnvirons.cellSize.h / 2)
  1948.                     lineOffset++;
  1949.             }
  1950.             
  1951.             // calculate offset into 'virtual' buffer.
  1952.             charOffset = GetLineStart(line) + lineOffset;
  1953.         }
  1954.     }
  1955.  
  1956.     return charOffset;
  1957. }
  1958.  
  1959. /******************************************************************************
  1960.  GetCharPoint (OVERRIDE)
  1961.  
  1962.          Return the Frame coordinates of the character at the given offset
  1963.          in the text buffer.        
  1964.  ******************************************************************************/
  1965.  
  1966. void    CTermPane::GetCharPoint( long charOffset, LongPt *aPt)
  1967. {
  1968.     long    line;
  1969.     short    vertInset, horzInset;
  1970.  
  1971.     TermEnvironRec    theEnvirons;
  1972.  
  1973.     GetEnvirons(&theEnvirons);
  1974.     
  1975.     if (charOffset > itsScrollBuffer->GetTextLength())
  1976.     {
  1977.         vertInset = theEnvirons.slop.v + theEnvirons.auxSpace.top;
  1978.         horzInset = theEnvirons.slop.h + theEnvirons.auxSpace.left;
  1979.     }
  1980.     else
  1981.     {
  1982.         vertInset = theEnvirons.slop.v;
  1983.         horzInset = theEnvirons.slop.h;
  1984.     }
  1985.     
  1986.     /* Ensure that the offset is within bounds */
  1987.     
  1988.     charOffset = Max(charOffset, 0);
  1989.     charOffset = Min(charOffset, GetLength());
  1990.  
  1991.     line = FindLine(charOffset);
  1992.         
  1993.     aPt->v = vertInset + (line * theEnvirons.cellSize.v);
  1994.     aPt->h = horzInset + ((charOffset - GetLineStart(line)) * theEnvirons.cellSize.h);
  1995. }
  1996.  
  1997. void    CTermPane::GetTextStyle( short *whichAttributes, TextStyle *aStyle)
  1998. {
  1999. }
  2000.  
  2001. void    CTermPane::GetCharStyle( long charOffset, TextStyle *theStyle)
  2002. {
  2003. }
  2004.  
  2005. /******************************************************************************
  2006.  FindLine (OVERRIDE)
  2007.  
  2008.         Find line in 'virtual' buffer that contains the given character.
  2009.  ******************************************************************************/
  2010.  
  2011. long    CTermPane::FindLine(long charPos)
  2012. {
  2013.     long    line;
  2014.     
  2015.     if (charPos > itsScrollBuffer->GetTextLength())
  2016.     {
  2017.         // find in terminal region
  2018.         TermEnvironRec    theEnvirons;
  2019.         TermDataBlock    theDataBlock;
  2020.         short            termLine;
  2021.         long            totLen = 0L;
  2022.     
  2023.         GetEnvirons(&theEnvirons);
  2024.         
  2025.         for (termLine = 1; termLine <= theEnvirons.textRows; termLine++)
  2026.         {
  2027.             GetLine(termLine,&theDataBlock);
  2028.             
  2029.             HLock(theDataBlock.theData);
  2030.             totLen += strlen(*theDataBlock.theData);
  2031.             HUnlock(theDataBlock.theData);
  2032.             
  2033.             DisposHandle(theDataBlock.theData);
  2034.             
  2035.             if (charPos < totLen)
  2036.                 break;
  2037.         }
  2038.     
  2039.         line = (termLine - 1) + itsScrollBuffer->GetNumLines();
  2040.     }
  2041.     else
  2042.     {
  2043.         line = itsScrollBuffer->FindLine(charPos);
  2044.     }
  2045.     
  2046.     return line;
  2047. }
  2048.  
  2049. /******************************************************************************
  2050.  GetLength {OVERRIDE}
  2051.  
  2052.          Return the number of characters in the 'virtual' buffer.
  2053.  ******************************************************************************/
  2054.  
  2055. long    CTermPane::GetLength( void)
  2056. {
  2057.     return TerminalTextLength(-1,-1) + itsScrollBuffer->GetTextLength();
  2058. }
  2059.  
  2060. /******************************************************************************
  2061.  GetLineStart
  2062.  
  2063.          Return the offset of the character at the start of the given line. 
  2064.          The line number parameter is zero-based.
  2065.  ******************************************************************************/
  2066.  
  2067. long    CTermPane::GetLineStart(long line)
  2068. {
  2069.     long charOffset = 0L;
  2070.     
  2071.     // calculate offset into 'virtual' buffer.
  2072.     if (line < itsScrollBuffer->GetNumLines())
  2073.     {
  2074.         // it's wholly contained in the scrollback buffer
  2075.         charOffset = itsScrollBuffer->GetLineStart(line);
  2076.     }
  2077.     else
  2078.     {
  2079.         long    start, len;
  2080.         
  2081.         // it's in the terminal region, so offset it by total amount in scrollback buffer.
  2082.         line -= itsScrollBuffer->GetNumLines();
  2083.         
  2084.         GetLineInfo(line, &start, &len);
  2085.         
  2086.         charOffset = itsScrollBuffer->GetTextLength() + start;
  2087.     }
  2088.     return charOffset;
  2089. }
  2090.  
  2091. /******************************************************************************
  2092.  GetLineEnd
  2093.  
  2094.          Return the offset of the character at the end of the given line. 
  2095.          The line number parameter is zero-based.
  2096.  ******************************************************************************/
  2097.  
  2098. long    CTermPane::GetLineEnd(long line)
  2099. {
  2100.     long charOffset = 0L;
  2101.     
  2102.     // calculate offset into 'virtual' buffer.
  2103.     if (line < itsScrollBuffer->GetNumLines())
  2104.     {
  2105.         // it's wholly contained in the scrollback buffer
  2106.         charOffset = itsScrollBuffer->GetLineEnd(line);
  2107.     }
  2108.     else
  2109.     {
  2110.         long    start, len;
  2111.         
  2112.         // it's in the terminal region, so offset it by total amount in scrollback buffer.
  2113.         line -= itsScrollBuffer->GetNumLines();
  2114.         
  2115.         GetLineInfo(line, &start, &len);
  2116.         
  2117.         charOffset = itsScrollBuffer->GetTextLength() + start + len;
  2118.     }
  2119.     return charOffset;
  2120. }
  2121.  
  2122. /******************************************************************************
  2123.  GetLineLength
  2124.  
  2125.          Return the length of the given line. 
  2126.          The line number parameter is zero-based.
  2127.  ******************************************************************************/
  2128.  
  2129. long    CTermPane::GetLineLength(long line)
  2130. {
  2131.     long lineLength = 0L;
  2132.     
  2133.     // calculate offset into 'virtual' buffer.
  2134.     if (line < itsScrollBuffer->GetNumLines())
  2135.     {
  2136.         // it's wholly contained in the scrollback buffer
  2137.         lineLength = itsScrollBuffer->GetLineLength(line);
  2138.     }
  2139.     else
  2140.     {
  2141.         long    start;
  2142.         
  2143.         // it's in the terminal region, so offset it by total amount in scrollback buffer.
  2144.         line -= itsScrollBuffer->GetNumLines();
  2145.         
  2146.         GetLineInfo(line, &start, &lineLength);
  2147.     }
  2148.     return lineLength;
  2149. }
  2150.  
  2151. /* ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ */
  2152.  
  2153. /*
  2154.  * TypeChar
  2155.  *
  2156.  * Type simulation
  2157.  *
  2158.  * theChar:        char to be typed
  2159.  *
  2160.  */
  2161.  
  2162. void    CTermPane::TypeChar(char theChar, short theModifiers)
  2163. {
  2164.     EventRecord    theEvent;
  2165.     long        finalTicks;
  2166.     
  2167.     theEvent.what = keyDown;
  2168.     theEvent.message = theChar;
  2169.     theEvent.modifiers = 0;
  2170.     
  2171.     Delay(CHAR_DELAY_TICKS,&finalTicks);
  2172.     
  2173.     this->DoKeyDown(theChar,0,&theEvent);
  2174. }    
  2175.  
  2176. long    CTermPane::GetSpacingCmd( void)
  2177. {
  2178.     return 0L;
  2179. }
  2180.  
  2181. /* ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ */
  2182.  
  2183. /*
  2184.  * GetNumLines -    (OVERRIDE) Get total # of lines, including cached lines. 
  2185.  *
  2186.  * 
  2187.  *
  2188.  */
  2189.  
  2190. long CTermPane::GetNumLines(void)
  2191. {
  2192.     TermEnvironRec    theEnvirons;
  2193.     
  2194.     GetEnvirons(&theEnvirons);
  2195.     
  2196.     return theEnvirons.textRows + numCachedLines;
  2197. }
  2198.  
  2199. Handle    CTermPane::CopyTextRange( long start, long end)
  2200. {
  2201.     return NULL;
  2202. }
  2203.  
  2204. void    CTermPane::PerformEditCommand( long theCommand)
  2205. {
  2206. }
  2207.  
  2208. void    CTermPane::InsertTextPtr( Ptr text, long length, Boolean fRedraw)
  2209. {
  2210. }
  2211.  
  2212. /******************************************************************************
  2213.  GetLineInfo
  2214.  
  2215.          Get info about the given line. 
  2216.          The line number parameter is zero-based.
  2217.  ******************************************************************************/
  2218.  
  2219. void    CTermPane::GetLineInfo(long line, long *start, long *len)
  2220. {
  2221.     // find in terminal region
  2222.     TermEnvironRec    theEnvirons;
  2223.     TermDataBlock    theDataBlock;
  2224.     short            termLine;
  2225.     
  2226.     GetEnvirons(&theEnvirons);
  2227.         
  2228.     *start = *len = 0L;
  2229.     
  2230.     for (termLine = 1; termLine <= theEnvirons.textRows && (termLine - 1) <= line; termLine++)
  2231.     {
  2232.         *start += *len;
  2233.         
  2234.         GetLine(termLine,&theDataBlock);
  2235.         
  2236.         HLock(theDataBlock.theData);
  2237.         *len = strlen(*theDataBlock.theData);
  2238.         HUnlock(theDataBlock.theData);
  2239.         
  2240.         DisposHandle(theDataBlock.theData);
  2241.     }
  2242. }
  2243.  
  2244. /******************************************************************************
  2245.  SetTermOffset
  2246.  
  2247.          Move Terminal to its offset. 
  2248.  ******************************************************************************/
  2249.  
  2250. void    CTermPane::SetTermOffset(void)
  2251. {
  2252.     int                vDelta;
  2253.     Rect            viewRect;
  2254.     TermEnvironRec    theEnvirons;
  2255.     
  2256.     GetEnvirons(&theEnvirons);
  2257.     
  2258.     viewRect = (*itsTerm)->viewRect;
  2259.     vDelta = viewRect.top % theEnvirons.cellSize.v;
  2260.     
  2261.     if (vDelta < 0)
  2262.         vDelta += theEnvirons.cellSize.v;
  2263.     
  2264.     ScrollTerminal(0, topMargin - vDelta);
  2265. }
  2266.  
  2267. /******************************************************************************
  2268.  ScrollTerminal
  2269.  
  2270.          Move Terminal region within the frame. 
  2271.  ******************************************************************************/
  2272.  
  2273. void    CTermPane::ScrollTerminal(int hDelta, int vDelta)
  2274. {
  2275.     TMScroll(itsTerm,hDelta,vDelta);
  2276. }
  2277.  
  2278. /******************************************************************************
  2279.  GetCharAt
  2280.  
  2281.     Return the character at aPosition. The character and its size
  2282.     are returned in charBuf, and aPosition is updated with the starting
  2283.     position of the character. If there is no character, then
  2284.     Length(charBuf) is 0, and aPosition is not updated.
  2285.     
  2286.  ******************************************************************************/
  2287.  
  2288. void    CTermPane::GetCharAt(long *aPosition, tCharBuf charBuf)
  2289. {
  2290.     long    scrollBufLen = itsScrollBuffer->GetTextLength();
  2291.     
  2292.     if (*aPosition >= scrollBufLen && *aPosition < scrollBufLen + TerminalTextLength(-1,-1))
  2293.     {
  2294.         // find in terminal region
  2295.         TermEnvironRec    theEnvirons;
  2296.         TermDataBlock    theDataBlock;
  2297.         short            termLine;
  2298.         long            totLen = 0L;
  2299.     
  2300.         GetEnvirons(&theEnvirons);
  2301.         
  2302.         for (termLine = 1; termLine <= theEnvirons.textRows; termLine++)
  2303.         {
  2304.             long len;
  2305.             
  2306.             GetLine(termLine,&theDataBlock);
  2307.             
  2308.             char *dataStr = (char *)*theDataBlock.theData;
  2309.             
  2310.             HLock(theDataBlock.theData);
  2311.             len = strlen(dataStr);
  2312.             HUnlock(theDataBlock.theData);
  2313.             
  2314.             if (*aPosition < totLen + len)
  2315.             {
  2316.                 Length(charBuf) = 1;
  2317.                 charBuf[1] = dataStr[*aPosition - totLen];
  2318.                 DisposHandle(theDataBlock.theData);
  2319.                 break;
  2320.             }
  2321.             
  2322.             totLen += len;
  2323.             
  2324.             DisposHandle(theDataBlock.theData);
  2325.         }
  2326.     }
  2327.     else
  2328.     {
  2329.         itsScrollBuffer->GetCharAt(aPosition, charBuf);
  2330.     }
  2331.         
  2332. }
  2333.  
  2334. /******************************************************************************
  2335.  GetCharBefore
  2336.  
  2337.     Return the character before aPosition. The character and its size
  2338.     are returned in charBuf, and aPosition is updated with the starting
  2339.     position of the character. If there is no preceding character, then
  2340.     Length(charBuf) is 0, and aPosition is not updated.
  2341.     
  2342.  ******************************************************************************/
  2343.  
  2344. void    CTermPane::GetCharBefore(long *aPosition, tCharBuf charBuf)
  2345. {
  2346.     long    totLength = GetLength();
  2347.     
  2348.     if ((totLength > 0) && (*aPosition <= totLength))
  2349.     {
  2350.         (*aPosition)--;
  2351.         GetCharAt(aPosition, charBuf);
  2352.     }
  2353. }
  2354.  
  2355. /******************************************************************************
  2356.  GetCharAfter
  2357.  
  2358.     Return the character after aPosition. The character and its size
  2359.     are returned in charBuf, and aPosition is updated with the starting
  2360.     position of the character. If there is no following character, then
  2361.     Length(charBuf) is 0, and aPosition is not updated.
  2362.  
  2363.  ******************************************************************************/
  2364.  
  2365. void    CTermPane::GetCharAfter(long *aPosition, tCharBuf charBuf)
  2366. {
  2367.     long    totLength = GetLength();
  2368.     
  2369.     if ((totLength > 0) && (*aPosition < totLength - 1))
  2370.     {
  2371.         (*aPosition)++;
  2372.         GetCharAt(aPosition, charBuf);
  2373.     }
  2374. }
  2375.  
  2376. /*
  2377.  * given a pixel count, return number of lines contained
  2378.  *
  2379.  * 
  2380.  *
  2381.  */
  2382.  
  2383. short    CTermPane::PixelsToLines(short    pixCount)
  2384. {
  2385.  short            windowSize,lineSize,ourSize;
  2386.  TermEnvironRec theEnvirons;
  2387.  
  2388.  GetEnvirons(&theEnvirons);
  2389.  
  2390.  lineSize = theEnvirons.cellSize.v;
  2391.  ourSize = pixCount / lineSize;
  2392.     
  2393.  if (ourSize > theEnvirons.textRows)
  2394.  {
  2395.      windowSize = theEnvirons.textRows;
  2396.  }
  2397.  else
  2398.  {
  2399.     windowSize = ourSize;
  2400.  }
  2401.  
  2402.  return (windowSize);
  2403. }
  2404.  
  2405. /* ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ */
  2406.  
  2407. /*
  2408.  * GetTermExtent
  2409.  *
  2410.  * Return the size (in char rows and columns) of the terminal pane
  2411.  *
  2412.  * theHExtent:    Nb of columns
  2413.  * theVExtent:    Nb of rows
  2414.  *
  2415.  */
  2416.  
  2417. void CTermPane::GetTermExtent(long *theHExtent,long *theVExtent)
  2418. {
  2419.     TermEnvironRec theEnvirons;
  2420.     
  2421.     this->GetEnvirons(&theEnvirons);
  2422.  
  2423.     *theHExtent = theEnvirons.textCols;
  2424.     *theVExtent = theEnvirons.textRows;
  2425. }
  2426.  
  2427. /* ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ */
  2428.  
  2429. /*
  2430.  * AdjustBounds -    adjust the size of the virtual pane to reflect total # of 
  2431.  *                    lines in the terminal pane, including cached ones.
  2432.  *
  2433.  * 
  2434.  *
  2435.  */
  2436.  
  2437. void    CTermPane::AdjustBounds(void)
  2438. {
  2439.     LongRect    newBounds;
  2440.     LongPt        newPoint;
  2441.     long        numTermCols, numTermRows;
  2442.     SignedByte    savedState;
  2443.     
  2444.     savedState = HGetState((Handle)itsTerm);
  2445.     HLock((Handle)itsTerm);
  2446.     
  2447.     QDToLongRect(&((*itsTerm)->viewRect),&newBounds);
  2448.     OffsetLongRect(&newBounds,-(newBounds.left),-(newBounds.top));
  2449.     
  2450.     GetExtent(&numTermCols, &numTermRows);
  2451.     newBounds.right = numTermCols;
  2452.     newBounds.bottom = numTermRows;
  2453.     
  2454.     GetPosition(&newPoint);
  2455.     
  2456.     SetBounds(&newBounds);
  2457.     SetPosition(&newPoint);
  2458.     
  2459.     HSetState((Handle)itsTerm,savedState);
  2460. }
  2461.  
  2462. /* ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ */
  2463.  
  2464. /*
  2465.  * AdjustTermPosition -    after terminal choose, adjust any terminal parameters.
  2466.  *
  2467.  * 
  2468.  *
  2469.  */
  2470.  
  2471. void    CTermPane::AdjustTermPosition(TermPtr oldRecord, TermEnvironRec *theOldEnvirons)
  2472. {
  2473.     TermEnvironRec    theEnvirons;
  2474.  
  2475.     GetEnvirons(&theEnvirons);
  2476.     
  2477.     if (theEnvirons.cellSize.v != theOldEnvirons->cellSize.v ||
  2478.         theEnvirons.cellSize.h != theOldEnvirons->cellSize.h)
  2479.     {
  2480.         long    oldVertOffset,oldHorzOffset,vertOffset,horzOffset;
  2481.         int        vDelta;
  2482.         
  2483.         oldVertOffset = oldRecord->viewRect.top / theOldEnvirons->cellSize.v;
  2484.         oldHorzOffset = oldRecord->viewRect.left / theOldEnvirons->cellSize.h;
  2485.         
  2486.         // make sure we leave don't scroll past the top margin.
  2487.         if (oldRecord->viewRect.top >= 0)
  2488.             vDelta = Max(0, oldRecord->viewRect.top - topMargin);
  2489.         else
  2490.             vDelta = Min(0, oldRecord->viewRect.top + topMargin);
  2491.     
  2492.         vertOffset = ((theEnvirons.cellSize.v * oldVertOffset) - vDelta);
  2493.         horzOffset = ((theEnvirons.cellSize.h * oldHorzOffset) - oldRecord->viewRect.left);
  2494.     
  2495.         ScrollTerminal(horzOffset,vertOffset);
  2496.     }
  2497. }
  2498.     
  2499. /* ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ */
  2500.  
  2501. /*
  2502.  * RefreshLine -    refresh the given line.
  2503.  *
  2504.  * 
  2505.  *
  2506.  */
  2507.  
  2508. void    CTermPane::RefreshLine(int line)
  2509. {
  2510.     Rect    r;
  2511.     
  2512.     if (CalcLineRect(line,&r))
  2513.     {
  2514.         Draw(&r);
  2515.     }
  2516. }
  2517.  
  2518. /* ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ */
  2519.  
  2520. /*
  2521.  * CalcLineRect -    calculate bounding rectangle of given line.
  2522.  *
  2523.  * 
  2524.  *
  2525.  */
  2526.  
  2527. CTermPane::CalcLineRect(int line, Rect *lineRect)
  2528. {
  2529.     LongRect        theLongArea;                /* frame coordinates of region */
  2530.     int                offsetX, offsetY, pixelsX, pixelsY;
  2531.     TermEnvironRec    theEnvirons;
  2532.     
  2533.     GetEnvirons(&theEnvirons);
  2534.     
  2535.     offsetY = theEnvirons.slop.v;
  2536.     offsetX = theEnvirons.slop.h + theEnvirons.auxSpace.left;
  2537.     
  2538.     pixelsX = theEnvirons.cellSize.h;
  2539.     pixelsY = theEnvirons.cellSize.v;
  2540.     
  2541.     GetFrame(&theLongArea);
  2542.     FrameToQDR(&theLongArea,lineRect);
  2543.     
  2544.     lineRect->left += offsetX;
  2545.     lineRect->right -= theEnvirons.slop.h + theEnvirons.auxSpace.right;
  2546.     
  2547.     lineRect->top += (line * pixelsY) + offsetY;
  2548.     lineRect->bottom = lineRect->top + pixelsY;
  2549.     
  2550.     OffsetRect(lineRect,0,CACHE_LINE_OFFSET);
  2551.  
  2552.     return lineRect->bottom > lineRect->top;
  2553. }
  2554.  
  2555. /* ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ */
  2556.  
  2557. /*
  2558.  * DeltaTermSize -    determine the difference between current frame size and
  2559.  *                     terminal frame size.
  2560.  *
  2561.  */
  2562.  
  2563. void CTermPane::DeltaTermSize(int *deltaH, int *deltaV)
  2564. {
  2565.     Rect        viewRect;
  2566.     LongRect    termFrame;
  2567.     SignedByte    savedState;
  2568.     
  2569.     savedState = HGetState((Handle)itsTerm);
  2570.     HLock((Handle)itsTerm);
  2571.     
  2572.     //QDToLongRect(&((*itsTerm)->viewRect),&viewRect);
  2573.     CalcTermViewRect(&viewRect);
  2574.     GetFrame(&termFrame);
  2575.     
  2576.     *deltaH = RectWidth(&viewRect) - RectWidth(&termFrame);
  2577.     *deltaV = (RectHeight(&viewRect) + topMargin + CACHE_LINE_OFFSET) - RectHeight(&termFrame);
  2578.     
  2579.     HSetState((Handle)itsTerm,savedState);
  2580. }
  2581.     
  2582. //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  2583. // simple test to pump data to the terminal pane
  2584. //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  2585.  
  2586. void CTermPane::TestTerm(void)
  2587. {
  2588.  static    int    i;
  2589.  char    teststr[80];
  2590.  Point    itsPos;
  2591.  
  2592.  for (i=0; i<53; i++)
  2593.  {
  2594.     TMIdle(itsTerm);
  2595.      itsPos = GetCursor();
  2596.      sprintf(teststr,"This is a test, [yd] #%d (%d)... \n\r",i,itsPos.v);
  2597.      DoStream(teststr,strlen(teststr),cmFlagsEOM);
  2598.     TMIdle(itsTerm);
  2599.  }
  2600.        
  2601. }
  2602.  
  2603. /******************************************************************************
  2604.  DrawLineRange
  2605.  
  2606.         Internal method to draw the specified range of text lines.  Assumes
  2607.         the pane has been prepared.
  2608.  ******************************************************************************/
  2609.     
  2610. void CTermPane::DrawLineRange(long startLine, long endLine, long startLineOffset, Boolean erase)
  2611. {
  2612.     TermDataBlock    theDataBlock;
  2613.     Rect            drawRect;
  2614.     long            dline;
  2615.     
  2616.     GetLine(1,&theDataBlock);
  2617.     DisposHandle(theDataBlock.theData);
  2618.     
  2619.     for (dline = startLine; dline <= endLine; dline++)
  2620.     {
  2621.      int    soffset = dline + position.v;
  2622.      char    szBuffer[128];
  2623.      
  2624.      itsScrollBuffer->GetLine(soffset,(unsigned char *)szBuffer,sizeof(szBuffer));
  2625.      
  2626.      PtrToHand(szBuffer,&theDataBlock.theData,strlen(szBuffer));
  2627.     
  2628.      CalcLineRect(dline, &drawRect);
  2629.      EraseRect(&drawRect);
  2630.      
  2631.      TMPaint(itsTerm,&theDataBlock,&drawRect);
  2632.      DisposHandle(theDataBlock.theData);
  2633.     }
  2634. }
  2635.  
  2636. /******************************************************************************
  2637.  HiliteTextRange
  2638.  
  2639.         Internal method to highlight the given range of text.  Assumes
  2640.         the pane has been prepared.
  2641.  ******************************************************************************/
  2642.  
  2643. void    CTermPane::HiliteTextRange(long startChar, long endChar)
  2644. {
  2645.     long            startLine;
  2646.     long            endLine;
  2647.     LongPt            startPt;
  2648.     LongPt            endPt;
  2649.     LongRect        hiliteRect;
  2650.     PenState        penState;
  2651.     Rect            qdRect;
  2652.     Rect            termFrame;
  2653.     RgnHandle        hiliteRgn;
  2654.     RgnHandle        rectRgn;
  2655.     short            hSpan;
  2656.     short            vSpan, vTermSpan;
  2657.     short            lineHeight;
  2658.     short            charWidth;
  2659.     TermEnvironRec    theEnvirons;
  2660.     Boolean            isActive = reallyActive;
  2661.     long            scrollLen = itsScrollBuffer->GetTextLength();
  2662.     
  2663.     // if there's no scroll-buffer, there's nothing to hilight
  2664.     if (! scrollLen)
  2665.         return;
  2666.         
  2667.     // bounds check.
  2668.     startChar = Max(startChar, 0);
  2669.     startChar = Min(startChar, scrollLen);
  2670.     endChar = Max(endChar, 0);
  2671.     endChar = Min(endChar, scrollLen);
  2672.     endChar = Max(endChar, startChar);
  2673.     
  2674.     GetEnvirons(&theEnvirons);
  2675.     
  2676.     lineHeight = theEnvirons.cellSize.v;
  2677.     charWidth = theEnvirons.cellSize.h;
  2678.     
  2679.     LongToQDRect(&frame,&termFrame);
  2680.     
  2681.     vSpan = RectHeight(&termFrame) / theEnvirons.cellSize.v;
  2682.     
  2683.     CalcTermRect(&termFrame);
  2684.     
  2685.     if (isActive)
  2686.     {
  2687.         /* Outline the selection range if the pane is not active */
  2688.         
  2689.         if (!isActive)
  2690.         {
  2691.             hiliteRgn = NewRgn();
  2692.             rectRgn = NewRgn();
  2693.         }
  2694.         
  2695.         /* Get the starting and ending selection lines and the */
  2696.         /* number of lines spanned by the frame */
  2697.             
  2698.         startLine = FindLine(startChar);
  2699.         endLine = Min(FindLine(endChar),numCachedLines);
  2700.         startLine = Min(startLine,endLine);
  2701.         
  2702.         GetFrameSpan(&hSpan, &vTermSpan);
  2703.         
  2704.         /* Take a quick exit if the selection is not visible */
  2705.         /* within the frame span */
  2706.         
  2707.         if (startLine >= position.v + vSpan || endLine < position.v)
  2708.             return;
  2709.         
  2710.         /* Adjust the starting and ending selection lines if they */
  2711.         /* are outside the frame */
  2712.         
  2713.         if (startLine < position.v)
  2714.         {
  2715.             startLine = position.v;
  2716.             startChar = GetLineStart(startLine);
  2717.         }
  2718.         
  2719.         if (endLine >= position.v + vSpan)
  2720.         {
  2721.             endLine = position.v + vSpan;
  2722.             endChar = GetLineStart(endLine);
  2723.         }
  2724.         
  2725.         /* Get the frame coordinates corresponding to the */
  2726.         /* start and end of the selection range */
  2727.             
  2728.         GetCharPoint(startChar, &startPt);
  2729.         GetCharPoint(endChar, &endPt);
  2730.         
  2731.         /* Adjust the horizontal coordinates if the either of the starting */
  2732.         /* or ending characters lies at the beginning of a line */
  2733.         
  2734.         if (startChar == GetLineStart(startLine))
  2735.             startPt.h = termFrame.left;
  2736.         if (endChar == GetLineStart(endLine))
  2737.             endPt.h = termFrame.left;
  2738.         
  2739.         /* Check for and handle a multiple-line selection range */
  2740.         
  2741.         if (startPt.v != endPt.v)
  2742.         {
  2743.             /* Highlight the first line of the selection range */
  2744.             
  2745.             SetLongRect(&hiliteRect, startPt.h, startPt.v, termFrame.right, startPt.v + lineHeight);
  2746.             FrameToQDR(&hiliteRect, &qdRect);
  2747.             OffsetRect(&qdRect,-(position.h * charWidth),-(position.v * lineHeight));
  2748.             
  2749.             if (isActive)
  2750.                 HiliteRect(&qdRect);
  2751.             else
  2752.             {
  2753.                 qdRect.left -= 1;
  2754.                 RectRgn(rectRgn, &qdRect);
  2755.                 UnionRgn(rectRgn, hiliteRgn, hiliteRgn);
  2756.             }
  2757.             
  2758.             /* Highlight the middle lines of the selection range */
  2759.             
  2760.             hiliteRect.left = termFrame.left;
  2761.             
  2762.             if (isActive)
  2763.             {
  2764.                 FrameToQDR(&hiliteRect, &qdRect);
  2765.                 OffsetRect(&qdRect,-(position.h * charWidth),-(position.v * lineHeight));
  2766.                 
  2767.                 while (++startLine < endLine)
  2768.                 {
  2769.                     qdRect.top += lineHeight;
  2770.                     qdRect.bottom += lineHeight;
  2771.                     HiliteRect(&qdRect);
  2772.                 }
  2773.             }
  2774.             else
  2775.             {
  2776.                 hiliteRect.top += lineHeight;
  2777.                 hiliteRect.left -= 1;
  2778.                 hiliteRect.bottom = endPt.v + 1;
  2779.                 FrameToQDR(&hiliteRect, &qdRect);
  2780.                 OffsetRect(&qdRect,-(position.h),-(position.v));
  2781.                 RectRgn(rectRgn, &qdRect);
  2782.                 UnionRgn(rectRgn, hiliteRgn, hiliteRgn);
  2783.             }
  2784.             
  2785.             SetLongPt(&startPt, hiliteRect.left, endPt.v);
  2786.         }
  2787.         
  2788.         /* Hilite the last part of the selection range */
  2789.         
  2790.         SetLongRect(&hiliteRect, startPt.h, endPt.v, endPt.h, endPt.v + lineHeight);
  2791.         FrameToQDR(&hiliteRect, &qdRect);
  2792.         OffsetRect(&qdRect,-(position.h * charWidth),-(position.v * lineHeight));
  2793.         
  2794.         if (isActive)
  2795.             HiliteRect(&qdRect);
  2796.         else
  2797.         {
  2798.             if (qdRect.right > qdRect.left + 1)
  2799.             {
  2800.                 qdRect.bottom += 1;
  2801.                 RectRgn(rectRgn, &qdRect);
  2802.                 UnionRgn(rectRgn, hiliteRgn, hiliteRgn);
  2803.             }
  2804.             
  2805.             /* Intersect the highlight region with the pane frame */
  2806.             
  2807.             FrameToQDR(&frame, &qdRect);
  2808.             RectRgn(rectRgn, &qdRect);
  2809.             SectRgn(rectRgn, hiliteRgn, hiliteRgn);
  2810.             DisposeRgn(rectRgn);
  2811.             
  2812.             /* Outline the highlight region */
  2813.             
  2814.             GetPenState(&penState);
  2815.             PenNormal();
  2816.             PenMode(patXor);
  2817.             FrameRgn(hiliteRgn);
  2818.             DisposeRgn(hiliteRgn);
  2819.             SetPenState(&penState);
  2820.         }
  2821.     }
  2822. }
  2823.  
  2824. /******************************************************************************
  2825.  HiliteRect
  2826.     
  2827.         Hilite the specified rectangle.  The rectangle is in QuickDraw
  2828.         coordinates.
  2829.  ******************************************************************************/
  2830.  
  2831. void    CTermPane::HiliteRect(const Rect *hiliteRect)
  2832. {
  2833.     SetHiliteMode();
  2834.     InvertRect(hiliteRect);
  2835. }
  2836.  
  2837. /******************************************************************************
  2838.  CalcWordBreak
  2839.     
  2840.         Return the character offset at which the next word break in the
  2841.         specified direction should occur.
  2842.  ******************************************************************************/
  2843.  
  2844. #define        TestBit(p,b)    (((long *)(p))[(b) >> 5] & (0x80000000U >> ((b) & 0x1F)))
  2845.  
  2846. long    CTermPane::CalcWordBreak(register long charPos, BreakDirection direction)
  2847. {
  2848.     tCharBuf         charBuf;
  2849.     register long    textLength;
  2850.     register Byte    c;
  2851.     static long        wordBreaks[8] = {    /* Packed boolean flags to indicate    */
  2852.         0x00000000, 0x0000FFC0,            /* whether or not a character is a    */
  2853.         0x7FFFFFE1, 0x7FFFFFE0,            /* word break character                */
  2854.         0x00000000, 0x00000000,
  2855.         0x00000000, 0x00000000
  2856.     };
  2857.     
  2858.     if (direction == kBreakLeft)
  2859.     {
  2860.         GetCharBefore(&charPos, charBuf);
  2861.         
  2862.         while (charPos && (c = charBuf[1], TestBit(wordBreaks, c)))
  2863.         {
  2864.             GetCharBefore(&charPos, charBuf);
  2865.         }
  2866.                 
  2867.         return (charPos > 0 ? charPos + 1 : 0);
  2868.     }
  2869.     else
  2870.     {
  2871.         textLength = itsScrollBuffer->GetTextLength();
  2872.         
  2873.         GetCharAfter(&charPos, charBuf);
  2874.         
  2875.         while (charPos < textLength && (c = charBuf[1], TestBit(wordBreaks, c)))
  2876.         {
  2877.             GetCharAfter(&charPos, charBuf);
  2878.         }
  2879.         
  2880.         return (charPos);
  2881.     }
  2882. }
  2883.  
  2884. /******************************************************************************
  2885.  SetSelection {OVERRIDE}
  2886.  
  2887.          Sets the selected text to the range corresponding to character
  2888.          positions selStart through selEnd.
  2889.  ******************************************************************************/
  2890.  
  2891. void    CTermPane::SetSelection( long selStart, long selEnd, Boolean fRedraw)
  2892. {
  2893.         /* Ensure that the positions are valid */
  2894.     
  2895.     selStart = Max(selStart, 0);
  2896.     selStart = Min(selStart, GetLength());
  2897.     selEnd = Max(selEnd, 0);
  2898.     selEnd = Min(selEnd, GetLength());
  2899.     selEnd = Max(selEnd, selStart);
  2900.     
  2901.         /* Take a quick exit if the selection range isn't being changed */
  2902.     
  2903.     if (selStart == itsSelStart && selEnd == itsSelEnd)
  2904.         return;
  2905.     
  2906.         /* Unhilite the old selection range if redraw was specified */
  2907.         
  2908.     if (fRedraw)
  2909.     {
  2910.         Prepare();
  2911.         
  2912.         if (itsSelStart != itsSelEnd)
  2913.             HiliteTextRange(itsSelStart, itsSelEnd);
  2914.     }
  2915.     
  2916.         /* Update our instance variables */
  2917.     
  2918.     itsSelStart = selStart;
  2919.     itsSelEnd = selEnd;
  2920.     //upDownArrow = FALSE;
  2921.     
  2922.         /* Ensure that the anchor point is one of the selection endpoints */
  2923.     
  2924.     if (itsSelAnchor != selStart && itsSelAnchor != selEnd)
  2925.         itsSelAnchor = selStart;
  2926.         
  2927.         /* Hilite the old selection range if redraw was specified */
  2928.         
  2929.     if (fRedraw && selStart != selEnd)
  2930.     {
  2931.         HiliteTextRange(selStart, selEnd);
  2932.     }
  2933. }
  2934.  
  2935. void    CTermPane::GetSelection( long *selStart, long *selEnd)
  2936. {
  2937.     *selStart = itsSelStart;
  2938.     *selEnd = itsSelEnd;
  2939. }
  2940.  
  2941. /******************************************************************************
  2942.  LinesScrolledUp
  2943.  
  2944.         Calculate how many lines were scrolled up.
  2945.  ******************************************************************************/
  2946.  
  2947. long CTermPane::LinesScrolledUp(void)
  2948. {
  2949.     Rect            viewRect, termRect;
  2950.     TermEnvironRec    theEnvirons;
  2951.     
  2952.     GetEnvirons(&theEnvirons);
  2953.     
  2954.     viewRect = (*itsTerm)->viewRect;
  2955.     termRect = (*itsTerm)->termRect;
  2956.     
  2957.     return (viewRect.top - termRect.top) / theEnvirons.cellSize.v;
  2958. }
  2959.     
  2960. /******************************************************************************
  2961.  LinesScrolledDown
  2962.  
  2963.         Calculate how many lines are beneath the last visible liRgn,&frameRect);
  2964.     RectRgn(termRgn,&termRect);
  2965.  
  2966.     DiffRgn(frameRgn,termRgn,borderRgn);    // border
  2967.     SetClip(borderRgn);
  2968.     EraseRgn(borderRgn);                    // border erased
  2969.     
  2970.     DisposeRgn(termRgn);
  2971.     DisposeRgn(frameRgn);
  2972.     DisposeRgn(borderRgn);
  2973.     
  2974.     Prepare();                                // restore clipping region
  2975.     
  2976.     HSetState((Handle)itsTerm,savedState);
  2977. }
  2978.  
  2979. /******************************************************************************
  2980.  TerminalTextLength
  2981.  
  2982.         calculate number of characters in TM buffer.
  2983.  ******************************************************************************/
  2984.  
  2985. long    CTermPane::TerminalTextLength(long startLine, long endLine)
  2986. {
  2987.     TermEnvironRec    theEnvirons;
  2988.     TermDataBlock    theDataBlock;
  2989.     short            lineno, firstDataLine;
  2990.     long            totLen = 0L;
  2991.     
  2992.     GetEnvirons(&theEnvirons);
  2993.     
  2994.     // get last line that has real data.
  2995.     for (firstDataLine = theEnvirons.textRows; firstDataLine >= 1; firstDataLine--)
  2996.     {
  2997.         GetLine(firstDataLine,&theDataBlock);
  2998.         
  2999.         char firstChar = *TrimRight(*theDataBlock.theData);
  3000.         
  3001.         DisposHandle(theDataBlock.theData);
  3002.         
  3003.         if (firstChar) break;
  3004.     }
  3005.     
  3006.     if (startLine < 1)
  3007.         startLine = 1;
  3008.     
  3009.     if (endLine < 1)
  3010.         endLine = theEnvirons.textRows;
  3011.     
  3012.     // limit to last line that has data.
  3013.     endLine = Min(endLine,firstDataLine);
  3014.         
  3015.     for (lineno = startLine; lineno <= endLine; lineno++)
  3016.     {
  3017.         GetLine(lineno,&theDataBlock);
  3018.         
  3019.         HLock(theDataBlock.theData);
  3020.         if (lineno < endLine)
  3021.             totLen += strlen(*theDataBlock.theData);
  3022.         else
  3023.             totLen += strlen(TrimRight(*theDataBlock.theData));
  3024.         HUnlock(theDataBlock.theData);
  3025.         
  3026.         DisposHandle(theDataBlock.theData);
  3027.     }
  3028.     
  3029.     return totLen;
  3030. }
  3031.  
  3032. /******************************************************************************
  3033.  ProcessCacheClick
  3034.  
  3035.         process a mouse click in the cache region.
  3036.         
  3037.         - Returns flag indicating if point was in cache region or not.
  3038.  ******************************************************************************/
  3039.  
  3040. Boolean CTermPane::ProcessCacheClick(Point hitPt)
  3041. {
  3042.     LongPt        autoScrollPt, framePt;
  3043.     long        line, selStart, selEnd;
  3044.     long        charOffset;
  3045.     SignedByte    savedState;
  3046.     Boolean        inCacheRegion;
  3047.     Boolean        wasLocked;
  3048.     TermEnvironRec    theEnvirons;
  3049.     
  3050.     savedState = HGetState((Handle)itsTerm);
  3051.     HLock((Handle)itsTerm);
  3052.     wasLocked = Lock(true);
  3053.     
  3054.     GetEnvirons(&theEnvirons);
  3055.     
  3056.     QDToFrame(hitPt, &framePt);
  3057.     autoScrollPt = framePt;
  3058.     PinInRect(&frame, &framePt);
  3059.     
  3060.     framePt.v += position.v * theEnvirons.cellSize.v;
  3061.     framePt.h += position.h * theEnvirons.cellSize.h;
  3062.     
  3063.     charOffset = GetCharOffset(&framePt);
  3064.     inCacheRegion = charOffset < itsScrollBuffer->GetTextLength();
  3065.  
  3066.     if (charOffset != lastCharOffset)
  3067.     {
  3068.         long        newSelStart, newSelEnd;
  3069.         short        vertInset, horzInset;
  3070.  
  3071.         vertInset = theEnvirons.slop.v;
  3072.         horzInset = theEnvirons.slop.h + theEnvirons.auxSpace.left;
  3073.                 
  3074.         /* Remember the current selection range */
  3075.             
  3076.         selStart = itsSelStart;
  3077.         selEnd = itsSelEnd;
  3078.             
  3079.         /* Determine the new selection range */
  3080.             
  3081.         if (gClicks == 1)
  3082.         {
  3083.             newSelStart = Min(origCharOffset, charOffset);
  3084.             newSelEnd = Max(origCharOffset, charOffset);
  3085.         }
  3086.         else if (gClicks == 2)
  3087.         {
  3088.             if (charOffset < origCharOffset)
  3089.             {
  3090.                 newSelStart = CalcWordBreak(charOffset, kBreakLeft);
  3091.                 newSelEnd = CalcWordBreak(origCharOffset, kBreakRight);
  3092.             }
  3093.             else
  3094.             {
  3095.                 newSelStart = CalcWordBreak(origCharOffset, kBreakLeft);
  3096.                 newSelEnd = CalcWordBreak(charOffset, kBreakRight);
  3097.             }
  3098.         }
  3099.         else
  3100.         {
  3101.             /* gClicks == 3 */
  3102.                 
  3103.             // line that has the desired character.
  3104.             line = (framePt.v - vertInset) / theEnvirons.cellSize.v;
  3105.                 
  3106.             if (line != lastLine)
  3107.             {
  3108.                 if (line < origLine)
  3109.                 {
  3110.                     newSelStart = GetLineStart(line);
  3111.                     newSelEnd = GetLineEnd(origLine);
  3112.                 }
  3113.                 else
  3114.                 {
  3115.                     newSelStart = GetLineStart(origLine);
  3116.                     newSelEnd = GetLineEnd(line);
  3117.                 }
  3118.                     
  3119.                 lastLine = line;
  3120.             }
  3121.             else
  3122.             {
  3123.                 newSelStart = selStart;
  3124.                 newSelEnd = selEnd;
  3125.             }
  3126.         }
  3127.             
  3128.         /* Adjust the hilited text */
  3129.             
  3130.         if (selStart != newSelStart)
  3131.             HiliteTextRange(Min(selStart, newSelStart), Max(selStart, newSelStart));
  3132.         if (selEnd != newSelEnd)
  3133.             HiliteTextRange(Min(selEnd, newSelEnd), Max(selEnd, newSelEnd));
  3134.             
  3135.         SetSelection(newSelStart, newSelEnd, kNoRedraw);
  3136.             
  3137.         /* Remember the current character offset */
  3138.             
  3139.         lastCharOffset = charOffset;
  3140.     }
  3141.     
  3142.     AutoScroll(&autoScrollPt);
  3143.     
  3144.     HSetState((Handle)itsTerm,savedState);
  3145.     Lock(wasLocked);
  3146.     
  3147.     return inCacheRegion;
  3148. }
  3149.  
  3150. /******************************************************************************
  3151.  DoCopy
  3152.  
  3153.         copy current selection to scrap.
  3154.         
  3155.  ******************************************************************************/
  3156.  
  3157. void CTermPane::DoCopy(short copyType)
  3158. {
  3159.     if (itsSelStart != itsSelEnd)
  3160.     {
  3161.         register long    scrollLen = itsScrollBuffer->GetTextLength();
  3162.         TermEnvironRec    theEnvirons;
  3163.         Handle            scrollHdl = nil, termHdl = nil;
  3164.         Handle            selectionHdl;
  3165.         ResType            selectionType = 'TEXT';
  3166.  
  3167.         GetEnvirons(&theEnvirons);
  3168.         
  3169.         // empty the clipboard.
  3170.         gClipboard->EmptyScrap();
  3171.         
  3172.         // put the selected contents of the scrollback buffer into a buffer.
  3173.         if (itsSelStart < scrollLen && theEnvirons.termType == tmTextTerminal)
  3174.         {
  3175.             long        selStart = Max(itsSelStart,0);
  3176.             long        selEnd = Min(itsSelEnd - 1,scrollLen);
  3177.             
  3178.             // if there really is something to copy, go ahead.
  3179.             if (selEnd > selStart)
  3180.             {
  3181.                 scrollHdl = itsScrollBuffer->CopyTextRange(selStart, selEnd);
  3182.                 
  3183.                 // if tab copy, replace spaces w/tabs
  3184.                 if (copyType == kTabCopy)
  3185.                     EnTab(scrollHdl);
  3186.             }
  3187.         }
  3188.         
  3189.         // now, put the selected contents of the terminal into a buffer.
  3190.         if (itsSelEnd >= scrollLen)
  3191.         {
  3192.             termHdl = NewHandle(0);
  3193.             TMGetSelect(itsTerm,termHdl,&selectionType);
  3194.             
  3195.             // if tab copy, replace spaces w/tabs
  3196.             if (copyType == kTabCopy)
  3197.                 EnTab(termHdl);
  3198.                 
  3199.             HLock(termHdl);
  3200.         }
  3201.         
  3202.         // make sure we have at least one valid handle
  3203.         if (termHdl || scrollHdl)
  3204.         {
  3205.             // if terminal buffer exists, may have to concatenate to the scrollback buffer
  3206.             if (termHdl)
  3207.             {
  3208.                 if (scrollHdl)
  3209.                 {
  3210.                     OSErr    theErr;
  3211.                     
  3212.                     // concatenate scrollback to terminal select buffer
  3213.                     theErr = HandAndHand(termHdl,scrollHdl);
  3214.                     FailOSErr(theErr);
  3215.                     
  3216.                     selectionHdl = scrollHdl;
  3217.                     
  3218.                     ForgetHandle(termHdl);
  3219.                 }
  3220.                 else 
  3221.                 {
  3222.                     selectionHdl = termHdl;
  3223.                 }
  3224.             }
  3225.             else selectionHdl = scrollHdl;
  3226.             
  3227.             // put either one or both buffers to the clipboard.
  3228.             gClipboard->PutData(selectionType,selectionHdl);
  3229.         }
  3230.         
  3231.         // dispose of the handles to selected data.
  3232.         ForgetHandle(scrollHdl);
  3233.         ForgetHandle(termHdl);
  3234.     }
  3235. }
  3236.  
  3237. /******************************************************************************
  3238.  GetFrameSpan - OVERIDE
  3239.  
  3240.  ******************************************************************************/
  3241.  
  3242. void    CTermPane::GetFrameSpan(
  3243.     short        *theHSpan,
  3244.     short        *theVSpan)
  3245. {
  3246.     Rect        newFrame;
  3247.               
  3248.     LongToQDRect(&frame,&newFrame);
  3249.         
  3250.     CalcTermRect(&newFrame);
  3251.         
  3252.     *theHSpan = (newFrame.right - newFrame.left) / hScale;
  3253.     *theVSpan = (newFrame.bottom - newFrame.top) / vScale;
  3254. }
  3255.  
  3256. /* ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ */
  3257.  
  3258. /*
  3259.  * EnTab
  3260.  *
  3261.  * Replace spaces w/tabs in buffer pointed to by given handle
  3262.  *
  3263.  */
  3264.  
  3265. long CTermPane::EnTab(Handle selectionHdl)
  3266. {
  3267.     register long            selectionLength,scrapLength;
  3268.     register short            i,scrapIndex,spacePending;
  3269.     register unsigned char    theChar;
  3270.     
  3271.     selectionLength = GetHandleSize(selectionHdl);
  3272.     scrapLength = selectionLength;
  3273.     
  3274.     spacePending = 0;
  3275.     scrapIndex = 0;
  3276.     
  3277.     for (i = 0;i < selectionLength;i ++)
  3278.     {    
  3279.         /* For each char… */
  3280.     
  3281.         theChar = (*selectionHdl)[i];
  3282.         
  3283.         if (theChar == SPACE)        /* Space char ? */
  3284.             spacePending ++;
  3285.         else
  3286.         {    
  3287.             if (spacePending > 1)
  3288.             {
  3289.                 /* More than one space ? */
  3290.                 (*selectionHdl)[scrapIndex] = TAB;
  3291.                 
  3292.                 scrapIndex ++;
  3293.                 scrapLength -= (spacePending - 1);
  3294.                 
  3295.                 (*selectionHdl)[scrapIndex] = theChar;
  3296.                 scrapIndex ++;
  3297.                 spacePending = 0;
  3298.             }
  3299.             else if (spacePending == 1)
  3300.             {
  3301.                 /* Exactly one space ? */
  3302.                 (*selectionHdl)[scrapIndex] = TAB;
  3303.                 scrapIndex ++;
  3304.                 (*selectionHdl)[scrapIndex] = theChar;
  3305.                 scrapIndex ++;
  3306.                 spacePending = 0;
  3307.             }
  3308.             else
  3309.             {
  3310.                 (*selectionHdl)[scrapIndex] = theChar;
  3311.                 scrapIndex ++;
  3312.             }                        
  3313.         }
  3314.     }
  3315.     
  3316.     SetHandleSize(selectionHdl,scrapLength);
  3317.     
  3318.     return scrapLength;
  3319. }